| 16 | namespace paddle::framework { |
| 17 | |
| 18 | void TransDataDevice(const DenseTensor &in, |
| 19 | const phi::Place &dst_place, |
| 20 | DenseTensor *out) { |
| 21 | VLOG(3) << "DeviceTransform in, src_place " << in.place() |
| 22 | << " dst_place: " << dst_place; |
| 23 | |
| 24 | PADDLE_ENFORCE_NE( |
| 25 | in.place().GetType(), |
| 26 | dst_place.GetType(), |
| 27 | common::errors::Unavailable("Currently, model parallelism is only " |
| 28 | "supported between CPU and CUDA.")); |
| 29 | |
| 30 | // NOTE(zhiqiu): Special case for CPU->NPU, avoid stream sync. |
| 31 | if (phi::is_cpu_place(in.place())) { |
| 32 | paddle::framework::TensorCopy( |
| 33 | in, dst_place, *phi::DeviceContextPool::Instance().Get(dst_place), out); |
| 34 | return; |
| 35 | } |
| 36 | |
| 37 | // NOTE(yy): TransDataDevice should wait for computation of input. |
| 38 | if (!phi::is_cuda_pinned_place(in.place())) { |
| 39 | phi::DeviceContextPool::Instance().Get(in.place())->Wait(); |
| 40 | phi::DeviceContextPool::Instance().Get(dst_place)->Wait(); |
| 41 | } |
| 42 | |
| 43 | // FIXME(zcd): TransDataDevice is used to transform data from GPU to CPU and |
| 44 | // the enforced checks have been done in GetDeviceContext, so the |
| 45 | // `dev_ctx->Wait()` is necessary. But `dev_ctx->Wait()` will make the program |
| 46 | // slow, especially when the number of elements is little, for example, |
| 47 | // the elements of learning rate are one and it's CPU side. |
| 48 | // One solution is to use a CUDA kernel to complete the copy operation when |
| 49 | // the transforming is from CPU to GPU and the number of elements is little. |
| 50 | // But the embarrassment is that this solution makes training slower. |
| 51 | TensorCopySync(in, dst_place, out); |
| 52 | } |
| 53 | |
| 54 | } // namespace paddle::framework |
no test coverage detected