| 319 | : OpKernel(context) {} |
| 320 | |
| 321 | void Compute(OpKernelContext* ctx) override { |
| 322 | const Tensor& alg_tensor = ctx->input(1); |
| 323 | const Tensor& shape_tensor = ctx->input(2); |
| 324 | const Tensor& counts_tensor = ctx->input(3); |
| 325 | const Tensor& probs_tensor = ctx->input(4); |
| 326 | |
| 327 | OP_REQUIRES(ctx, alg_tensor.dims() == 0, |
| 328 | errors::InvalidArgument("algorithm must be of shape [], not ", |
| 329 | alg_tensor.shape().DebugString())); |
| 330 | Algorithm alg = alg_tensor.flat<Algorithm>()(0); |
| 331 | |
| 332 | OP_REQUIRES( |
| 333 | ctx, TensorShapeUtils::IsVector(shape_tensor.shape()), |
| 334 | errors::InvalidArgument("Input shape should be a vector, got shape: ", |
| 335 | shape_tensor.shape().DebugString())); |
| 336 | int32 num_batches = shape_tensor.flat<int32>()(0); |
| 337 | |
| 338 | int32 samples_per_batch = 1; |
| 339 | const int32 num_dims = shape_tensor.dim_size(0); |
| 340 | for (int32 i = 1; i < num_dims; i++) { |
| 341 | samples_per_batch *= shape_tensor.flat<int32>()(i); |
| 342 | } |
| 343 | const int32 num_elements = num_batches * samples_per_batch; |
| 344 | |
| 345 | // Allocate the output before fudging num_batches and samples_per_batch. |
| 346 | auto shape_vec = shape_tensor.flat<int32>(); |
| 347 | TensorShape tensor_shape; |
| 348 | OP_REQUIRES_OK(ctx, TensorShapeUtils::MakeShape( |
| 349 | shape_vec.data(), shape_vec.size(), &tensor_shape)); |
| 350 | Tensor* samples_tensor; |
| 351 | OP_REQUIRES_OK(ctx, ctx->allocate_output(0, tensor_shape, &samples_tensor)); |
| 352 | |
| 353 | // Parameters must be 0-d or 1-d. |
| 354 | OP_REQUIRES(ctx, counts_tensor.dims() <= 1, |
| 355 | errors::InvalidArgument( |
| 356 | "Input counts should be a scalar or vector, got shape: ", |
| 357 | counts_tensor.shape().DebugString())); |
| 358 | OP_REQUIRES(ctx, probs_tensor.dims() <= 1, |
| 359 | errors::InvalidArgument( |
| 360 | "Input probs should be a scalar or vector, got shape: ", |
| 361 | probs_tensor.shape().DebugString())); |
| 362 | |
| 363 | if ((counts_tensor.dims() == 0 || counts_tensor.dim_size(0) == 1) && |
| 364 | (probs_tensor.dims() == 0 || probs_tensor.dim_size(0) == 1)) { |
| 365 | // All batches have the same parameters, so we can update the batch size |
| 366 | // to a reasonable value to improve parallelism (ensure enough batches, |
| 367 | // and no very small batches which have high overhead). |
| 368 | int32 size = num_batches * samples_per_batch; |
| 369 | int32 adjusted_samples = kDesiredBatchSize; |
| 370 | // Ensure adjusted_batches * adjusted_samples >= size. |
| 371 | int32 adjusted_batches = Eigen::divup(size, adjusted_samples); |
| 372 | num_batches = adjusted_batches; |
| 373 | samples_per_batch = adjusted_samples; |
| 374 | } else { |
| 375 | // Parameters must be broadcastable to the shape [num_batches]. |
| 376 | OP_REQUIRES( |
| 377 | ctx, |
| 378 | TensorShapeUtils::IsScalar(counts_tensor.shape()) || |
nothing calls this directly
no test coverage detected