| 421 | // TODO(sami) Not really a good way. Perhaps consider using thrust? |
| 422 | template <typename Op> |
| 423 | Status CountIf(OpKernelContext* context, const float* dev_array, const Op& op, |
| 424 | int num_elements, int* result) { |
| 425 | Tensor scratch_output; |
| 426 | Tensor workspace; |
| 427 | Tensor element_count; |
| 428 | size_t workspace_size = 0; |
| 429 | auto cuda_stream = tensorflow::GetGpuStream(context); |
| 430 | auto device = context->eigen_gpu_device(); |
| 431 | cub::DeviceSelect::If(nullptr, workspace_size, static_cast<float*>(nullptr), |
| 432 | static_cast<float*>(nullptr), |
| 433 | static_cast<int*>(nullptr), num_elements, op); |
| 434 | |
| 435 | TF_RETURN_IF_ERROR(context->allocate_temp( |
| 436 | DataType::DT_FLOAT, TensorShape({num_elements}), &scratch_output)); |
| 437 | TF_RETURN_IF_ERROR(context->allocate_temp( |
| 438 | DataType::DT_INT8, TensorShape({(int64)workspace_size}), &workspace)); |
| 439 | TF_RETURN_IF_ERROR(context->allocate_temp(DataType::DT_INT32, |
| 440 | TensorShape({1}), &element_count)); |
| 441 | cudaEvent_t copy_done; |
| 442 | TF_RETURN_IF_CUDA_ERROR( |
| 443 | cudaEventCreateWithFlags(©_done, cudaEventDisableTiming)); |
| 444 | TF_RETURN_IF_CUDA_ERROR(cub::DeviceSelect::If( |
| 445 | workspace.flat<int8>().data(), workspace_size, dev_array, |
| 446 | scratch_output.flat<float>().data(), element_count.flat<int32>().data(), |
| 447 | num_elements, op, cuda_stream)); |
| 448 | device.memcpyDeviceToHost(result, element_count.flat<int32>().data(), |
| 449 | sizeof(int)); |
| 450 | TF_RETURN_IF_CUDA_ERROR(cudaEventRecord(copy_done, device.stream())); |
| 451 | TF_RETURN_IF_CUDA_ERROR(cudaEventSynchronize(copy_done)); |
| 452 | return Status::OK(); |
| 453 | } |
| 454 | |
| 455 | template <typename Op> |
| 456 | Status CountIf(OpKernelContext* context, const float* dev_array, const Op& op, |
no test coverage detected