------------------------------------------------------------------------------
| 41 | |
| 42 | //------------------------------------------------------------------------------ |
| 43 | bool vtkDIYDataExchanger::AllToAll(const std::vector<vtkSmartPointer<vtkDataSet>>& sendBuffer, |
| 44 | const std::vector<int>& sendCounts, std::vector<vtkSmartPointer<vtkDataSet>>& recvBuffer, |
| 45 | std::vector<int>& recvCounts) |
| 46 | { |
| 47 | if (this->Controller == nullptr || (this->Controller->GetNumberOfProcesses() <= 1)) |
| 48 | { |
| 49 | recvBuffer = sendBuffer; |
| 50 | recvCounts = sendCounts; |
| 51 | return true; |
| 52 | } |
| 53 | |
| 54 | if (static_cast<int>(sendCounts.size()) != this->Controller->GetNumberOfProcesses()) |
| 55 | { |
| 56 | vtkErrorMacro("`sendCounts` size (" << sendCounts.size() << ") must match the number of ranks (" |
| 57 | << this->Controller->GetNumberOfProcesses() << ")."); |
| 58 | return false; |
| 59 | } |
| 60 | |
| 61 | diy::mpi::communicator comm = vtkDIYUtilities::GetCommunicator(this->Controller); |
| 62 | assert(static_cast<int>(sendCounts.size()) == comm.size()); |
| 63 | |
| 64 | std::vector<int> offsets(comm.size(), 0); |
| 65 | for (int cc = 1; cc < comm.size(); ++cc) |
| 66 | { |
| 67 | offsets[cc] = offsets[cc - 1] + sendCounts[cc - 1]; |
| 68 | } |
| 69 | assert((offsets.back() + sendCounts.back()) == static_cast<int>(sendBuffer.size())); |
| 70 | |
| 71 | // collect information from all ranks about who has data from whom. this helps |
| 72 | // us setup links. |
| 73 | std::vector<std::vector<int>> allCounts; |
| 74 | diy::mpi::all_gather(comm, sendCounts, allCounts); |
| 75 | |
| 76 | using VectorOfDataSet = std::vector<vtkSmartPointer<vtkDataSet>>; |
| 77 | using VectorOfVectorOfDataSet = std::vector<VectorOfDataSet>; |
| 78 | using BlockT = VectorOfVectorOfDataSet; |
| 79 | |
| 80 | diy::Master master( |
| 81 | comm, 1, -1, []() { return static_cast<void*>(new BlockT()); }, |
| 82 | [](void* b) { delete static_cast<BlockT*>(b); }); |
| 83 | |
| 84 | // note: each rank gets 1 DIY-block. |
| 85 | diy::ContiguousAssigner assigner(comm.size(), comm.size()); |
| 86 | |
| 87 | auto link = new diy::Link(); |
| 88 | |
| 89 | // add neighbours. |
| 90 | for (int gid = 0; gid < comm.size(); ++gid) |
| 91 | { |
| 92 | if (allCounts[comm.rank()][gid] > 0 || allCounts[gid][comm.rank()] > 0) |
| 93 | { |
| 94 | link->add_neighbor(diy::BlockID(gid, assigner.rank(gid))); |
| 95 | } |
| 96 | } |
| 97 | |
| 98 | auto block = new BlockT(comm.size()); |
| 99 | for (int rank = 0; rank < comm.size(); ++rank) |
| 100 | { |