| 381 | |
| 382 | template<typename Dtype> |
| 383 | void P2PSync<Dtype>::Prepare(const vector<int>& gpus, |
| 384 | vector<shared_ptr<P2PSync<Dtype> > >* syncs) { |
| 385 | // Pair devices for map-reduce synchronization |
| 386 | vector<DevicePair> pairs; |
| 387 | DevicePair::compute(gpus, &pairs); |
| 388 | ostringstream s; |
| 389 | for (int i = 1; i < pairs.size(); ++i) { |
| 390 | s << (i == 1 ? "" : ", ") << pairs[i].parent() << ":" << pairs[i].device(); |
| 391 | } |
| 392 | LOG(INFO)<< "GPUs pairs " << s.str(); |
| 393 | |
| 394 | SolverParameter param(solver_->param()); |
| 395 | |
| 396 | // Build the GPU tree by finding the parent for each solver |
| 397 | for (int attempts = 0; attempts < pairs.size(); ++attempts) { |
| 398 | for (int i = 1; i < pairs.size(); ++i) { |
| 399 | if (!syncs->at(i).get()) { |
| 400 | P2PSync<Dtype>* parent = NULL; |
| 401 | for (int j = 0; j < syncs->size(); ++j) { |
| 402 | P2PSync<Dtype>* sync = j == 0 ? this : syncs->at(j).get(); |
| 403 | if (sync) { |
| 404 | const SolverParameter& p = sync->solver()->param(); |
| 405 | if (p.device_id() == pairs[i].parent()) { |
| 406 | parent = sync; |
| 407 | } |
| 408 | } |
| 409 | } |
| 410 | if (parent) { |
| 411 | param.set_device_id(pairs[i].device()); |
| 412 | syncs->at(i).reset(new P2PSync<Dtype>(solver_, parent, param)); |
| 413 | parent->children_.push_back((P2PSync<Dtype>*) syncs->at(i).get()); |
| 414 | } |
| 415 | } |
| 416 | } |
| 417 | } |
| 418 | } |
| 419 | |
| 420 | template<typename Dtype> |
| 421 | void P2PSync<Dtype>::Run(const vector<int>& gpus) { |