| 6309 | } |
| 6310 | |
| 6311 | bool CudnnSupport::DoDepthConcatenate( |
| 6312 | Stream* stream, port::ArraySlice<dnn::BatchDescriptor> input_dimensions, |
| 6313 | port::ArraySlice<const DeviceMemory<float>*> input_data, |
| 6314 | DeviceMemory<float>* output_data) { |
| 6315 | CHECK_EQ(input_dimensions.size(), input_data.size()); |
| 6316 | |
| 6317 | for (const auto& dimensions : input_dimensions) { |
| 6318 | if (dimensions.layout() != dnn::DataLayout::kBatchDepthYX) { |
| 6319 | LOG(ERROR) << "CudnnSupport::DoDepthConcatenate currently only " |
| 6320 | "supports the kBatchDepthYX layout."; |
| 6321 | return false; |
| 6322 | } |
| 6323 | } |
| 6324 | |
| 6325 | if (input_dimensions.empty()) { |
| 6326 | return true; // Nothing to do. |
| 6327 | } |
| 6328 | |
| 6329 | dnn::BatchDescriptor output_dimensions = |
| 6330 | dnn::BatchDescriptor::DepthConcatenateOutputDescriptor(input_dimensions); |
| 6331 | |
| 6332 | const int64 area = output_dimensions.width() * output_dimensions.height(); |
| 6333 | const auto index = [area](int64 batch, int64 depth, int64 yx, |
| 6334 | int64 max_depth) { |
| 6335 | return (batch * max_depth + depth) * area + yx; |
| 6336 | }; |
| 6337 | |
| 6338 | std::vector<float> output_host(output_dimensions.ElementCount()); |
| 6339 | std::vector<float> tmp; |
| 6340 | int64 depth_sum = 0; |
| 6341 | for (size_t i = 0; i < input_data.size(); ++i) { |
| 6342 | const auto& dimensions = input_dimensions[i]; |
| 6343 | tmp.resize(dimensions.ElementCount()); |
| 6344 | stream->ThenMemcpyD2H<float>(*input_data[i], absl::MakeSpan(tmp)); |
| 6345 | port::Status block_status = stream->BlockHostUntilDone(); |
| 6346 | if (!block_status.ok()) { |
| 6347 | LOG(ERROR) << "BlockHostUntilDone failed: " << block_status; |
| 6348 | return false; |
| 6349 | } |
| 6350 | |
| 6351 | for (int64 batch = 0; batch < output_dimensions.count(); ++batch) { |
| 6352 | for (int64 yx = 0; yx < area; ++yx) { |
| 6353 | for (int64 depth = 0; depth < dimensions.feature_map_count(); ++depth) { |
| 6354 | LOG(INFO) << output_dimensions.ElementCount() << ' ' << batch << ' ' |
| 6355 | << yx << ' ' << depth; |
| 6356 | output_host[index(batch, depth + depth_sum, yx, |
| 6357 | output_dimensions.feature_map_count())] = |
| 6358 | tmp[index(batch, depth, yx, dimensions.feature_map_count())]; |
| 6359 | } |
| 6360 | } |
| 6361 | } |
| 6362 | depth_sum += dimensions.feature_map_count(); |
| 6363 | } |
| 6364 | stream->ThenMemcpyH2D<float>(output_host, output_data); |
| 6365 | return true; |
| 6366 | } |
| 6367 | |
| 6368 | bool CudnnSupport::DoElementwiseOperate( |
nothing calls this directly
no test coverage detected