Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/mercurial/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 使用MPI和C+从不同节点收集数据+;_C++_Mpi - Fatal编程技术网

C++ 使用MPI和C+从不同节点收集数据+;

C++ 使用MPI和C+从不同节点收集数据+;,c++,mpi,C++,Mpi,我正在做一个包含几个从节点和一个主节点的项目。在某个时刻,我需要从不同的从节点(主节点也可以被视为从节点)收集数据到主节点。数据可以是任何类型,但假设它是unsigned int。这就是数据在从属节点上的外观: 节点0:| chunk01 | chunk02 | chunk03 | chunk04 | 节点1:| chunk11 | chunk12 | chunk13 | chunk14 | 诺登:| chunkn1 | chunkn2 | chunkn3 | chunkn4 | 数据应该全部

我正在做一个包含几个从节点和一个主节点的项目。在某个时刻,我需要从不同的从节点(主节点也可以被视为从节点)收集数据到主节点。数据可以是任何类型,但假设它是unsigned int。这就是数据在从属节点上的外观:

节点0:| chunk01 | chunk02 | chunk03 | chunk04 |

节点1:| chunk11 | chunk12 | chunk13 | chunk14 |

诺登:| chunkn1 | chunkn2 | chunkn3 | chunkn4 |

数据应该全部收集到node0,如下所示:

节点0:| chunk01 | chunk11 | chunk21 | | | chunkn1 | chunk02 | chunk12 | | chunkn2 | | chunknm|

这意味着我们将每个节点的第一个块连接在一起,然后将每个节点的第二个块连接在一起

我不知道如何使用MPI_Gatherv来实现这一点,因为每个chunkij都有不同的大小,而且每个节点只知道自己的块大小和开始索引,而不知道其他节点的信息


我对MPI不太熟悉,所以我想知道是否有任何API可以将不同大小的数据从不同的节点收集到一个节点?

下面是一个可以编辑的示例,应该可以使用。这几乎肯定不是解决这个问题的最佳方法——我需要更多的代码细节来对此进行评论。我还没有检查它是否编译,但如果你修复了任何打字错误,我很乐意尝试修复任何未解决的错误

我也不知道效率对你有多重要——这项工作是每秒进行数百次还是每天进行一次?如果是后者,那么这段代码可能很好。我也假设C/C++。< /P>
// Populate this on each node from MPI_Comm_rank.
int myRank; 
// Populate this on each node from MPI_Comm_size.
int P; 
// Num chunks per core.
const int M = 4;  

// I'm assuming 0 is the master.
int masterNodeRank = 0; 

// Populate this. 
// It only needs to have meaningful data on the master node. 
//If master node doesn't have the data, fill with MPI_GATHER.
int* sizeOfEachChunkOnEachRank[M]; 
// Populate this. 
//It needs to exist on every 'slave' node.
int sizeOfMyChunks[M]; 

// Assuming you already have this array
// it should be the contiguous store of each core's data.
unsigned* myData; 
// This is what we'll gather all the data into on master node only.
unsigned* gatheredData = new unsigned[totalDataSize];
// This array will keep all of the displacements from each sending node.
int* displacements = new int[P];

// This keeps track of how many unsigneds we've received so far.
int totalCountSoFar = 0;

// We'll work through all the first chunks on each node at once, then all
// the second chunks, etc.
for(int localChunkNum = 0; localChunkNum < M; ++localChunkNum)
{
  // On the receiving node we need to calculate all the displacements
  // for the received data to go into the array
  if (myRank == masterNodeRank)
  {
    displacements[0] = 0;

    for(int otherCore = 1; otherCore < P; ++otherCore)
    {
      displacements[otherCore] = displacements[otherCore-1] + sizeOfEachChunkOnEachRank[localChunkNum][otherCore-1];
    }
  }

  // On all cores, we'll need to calculate how far into our local array
  // to start the sending from.      
  int myFirstIndex = 0;

  for(int previousChunk=0; previousChunk < localChunkNum; previousChunk++)
  {
    myFirstIndex += sizeOfMyChunks[previousChunk];
  }

  // Do the variable gather
  MPI_Gatherv(&myData[myFirstIndex], // Start address to send from
              sizeOfMyChunks[localChunkNum], // Number to send
              MPI_UNSIGNED, // Type to send
              &gatheredData[totalCountSoFar], // Start address to receive into
              sizeOfEachChunkOnEachRank[localChunkNum], // Number expected from each core
              displacements, // Displacements to receive into from each core
              MPI_UNSIGNED, // Type to receive
              masterNodeRank, // Receiving core rank
              MPI_COMM_WORLD); // MPI communicator.

  // If this is the receiving rank, update the count we've received so far
  // so that we don't overwrite data the next time we do the gather.
  // Note that the total received is the displacement to the receive from the
  // last core + the total received from that core.
  if(myRank == masterNodeRank)
  {
    totalCountSoFar += displacements[P-1] + sizeOfEachChunkOnEachRank[localChunkNum][P-1];
  }
}

delete[] displacements;
delete[] gatheredData;
//在MPI\u Comm\u秩的每个节点上填充此值。
int-myRank;
//从MPI_Comm_size在每个节点上填充此内容。
INTP;
//每个核心的块数。
常数int M=4;
//我假设0是主控。
int masterNodeRank=0;
//填充这个。
//它只需要在主节点上有有意义的数据。
//如果主节点没有数据,则使用MPI_聚集填充。
int*sizeOfEachChunkOnEachRank[M];
//填充这个。
//它需要存在于每个“从属”节点上。
int sizeOfMyChunks[M];
//假设您已经有了这个数组
//它应该是每个核心数据的连续存储。
无符号*myData;
//这是我们将仅在主节点上收集所有数据的内容。
unsigned*gatheredData=新的unsigned[totalDataSize];
//该阵列将保留每个发送节点的所有位移。
int*位移=新的int[P];
//这记录了到目前为止我们收到的未签名数量。
整数totalCountSoFar=0;
//我们将一次处理每个节点上的所有第一个块,然后是所有块
//第二块等等。
for(int localChunkNum=0;localChunkNum
普通1D阵列。使用指针。有时我会非常想念像
MPI\u Gatherw
…谢谢你的回答。这很有帮助。事实上,我试过这个,效果很好。虽然只有一个问题:我没有其他节点的位移值。我只有当前节点的位移。sizeOfEachChunkOnEachRank的情况也一样。无论如何,我设法使接收大小固定。这会增加很多无用的价值。因此,我将使用compact去掉所有这些值。至于效率。我对当前的解决方案很满意。@user1494585您可以使用一个额外的
MPI_Gather
调用从根的所有列组收集块大小,然后根计算排他前缀和以获得位移。