           N * D, P->data<float>(), P->mutable_data<float>(), &context_);
     } else {
       ProbCrossEntropyKernel<<<
-          CAFFE_GET_BLOCKS(N),
+          std::min(N, CAFFE_MAXIMUM_NUM_BLOCKS),
           CAFFE_CUDA_NUM_THREADS,
           0,
           context_.cuda_stream()>>>(

    const float* labeldata,
    const float* weights,
    float* Ydata) {
  CUDA_1D_KERNEL_LOOP(i, N) {
    float weight = weights ? weights[i] : 1.0;
    float total_prob = 0.0;
    Ydata[i] = 0.0;
    for (int j = 0; j < D; j++) {
      int idx = i * D + j;
      total_prob += labeldata[idx];
      CUDA_KERNEL_ASSERT(labeldata[idx] >= 0);
      Ydata[i] += -logf(max(Pdata[idx], FLT_MIN)) * labeldata[idx] * weight;
    }
    CUDA_KERNEL_ASSERT(abs(total_prob - 1.0) < 1e-5f);
  }
}


    float* dXdata,
    const float* weights) {
  if (weights == NULL) {
    CUDA_1D_KERNEL_LOOP(idx, N * D) {
      dXdata[idx] = Pdata[idx] - labeldata[idx];
    }
  } else {
    CUDA_1D_KERNEL_LOOP(idx, N * D) {
      dXdata[idx] = (Pdata[idx] - labeldata[idx]) * weights[idx / D];
    }
  }
}
