| 285 | |
| 286 | template<typename Dtype> |
| 287 | void P2PSync<Dtype>::on_start() { |
| 288 | #ifndef CPU_ONLY |
| 289 | #ifdef DEBUG |
| 290 | int device; |
| 291 | CUDA_CHECK(cudaGetDevice(&device)); |
| 292 | CHECK(device == solver_->param().device_id()); |
| 293 | #else |
| 294 | // CHECK(false); |
| 295 | #endif |
| 296 | |
| 297 | // Wait for update from parent |
| 298 | if (parent_) { |
| 299 | P2PSync<Dtype> *parent = queue_.pop(); |
| 300 | CHECK(parent == parent_); |
| 301 | } |
| 302 | |
| 303 | // Update children |
| 304 | for (int i = children_.size() - 1; i >= 0; i--) { |
| 305 | Dtype* src = data_; |
| 306 | Dtype* dst = children_[i]->data_; |
| 307 | |
| 308 | #ifdef DEBUG |
| 309 | cudaPointerAttributes attributes; |
| 310 | CUDA_CHECK(cudaPointerGetAttributes(&attributes, src)); |
| 311 | CHECK(attributes.device == device); |
| 312 | CUDA_CHECK(cudaPointerGetAttributes(&attributes, dst)); |
| 313 | CHECK(attributes.device == children_[i]->solver_->param().device_id()); |
| 314 | #endif |
| 315 | |
| 316 | CUDA_CHECK(cudaMemcpyAsync(dst, src, size_ * sizeof(Dtype), |
| 317 | cudaMemcpyDeviceToDevice, cudaStreamDefault)); |
| 318 | CUDA_CHECK(cudaStreamSynchronize(cudaStreamDefault)); |
| 319 | children_[i]->queue_.push(this); |
| 320 | } |
| 321 | #endif |
| 322 | } |
| 323 | |
| 324 | template<typename Dtype> |
| 325 | void P2PSync<Dtype>::on_gradients_ready() { |