将向量的一部分分配给从属进程 使用C++和OpenMPi,我想创建一个向量,然后在主进程中把向量的部分均匀地分配给要处理的从属进程。因此,如果向量有100个整数,并且有5个从进程,那么每个从进程将被发送一个包含20个整数的向量
下面是我尝试的代码,但它不起作用将向量的一部分分配给从属进程 使用C++和OpenMPi,我想创建一个向量,然后在主进程中把向量的部分均匀地分配给要处理的从属进程。因此,如果向量有100个整数,并且有5个从进程,那么每个从进程将被发送一个包含20个整数的向量,c++,vector,mpi,C++,Vector,Mpi,下面是我尝试的代码,但它不起作用 #include <iostream> #include <list> #include "mpi.h" #include <stdio.h> #include <stdlib.h> #include <vector> #include <algorithm> #include <map> #include <random> using namespace std;
#include <iostream>
#include <list>
#include "mpi.h"
#include <stdio.h>
#include <stdlib.h>
#include <vector>
#include <algorithm>
#include <map>
#include <random>
using namespace std;
int main(int argc, char **argv)
{
int rank, size, tag, rc, i;
MPI_Status status;
vector<int> vec(100);
vector<int> split_vec;
rc = MPI_Init(&argc, &argv);
rc = MPI_Comm_size(MPI_COMM_WORLD, &size);
rc = MPI_Comm_rank(MPI_COMM_WORLD, &rank);
tag=7;
random_device rd;
mt19937 gen(rd());
uniform_int_distribution<> dis;
generate(vec.begin(), vec.end(), [&](){ return dis(gen); });
// 100 ints / 5 slave processes
int split_size = vec.size() / size;
// split_size = size of vector of ints that each slave process should get
int offset = 0;
int j = 0;
int max = split_size;
if (rank==0) {
// master process
for (int i=1; i<size; ++i){
split_vec.clear();
while(j < max){
int elements = i_j + offset;
split_vec.push_back(vec[elements]);
j++;
}
max = max + split_size;
offset = offset + split_size;
MPI_Send(&split_vec[0], split_vec.size(), MPI_INT, i, tag, MPI_COMM_WORLD);
else{
// slaves processes
MPI_Recv(&split_vec[0], split_vec.size(), MPI_INT, 0, tag, MPI_COMM_WORLD, &status);
// process the vector
}
MPI_Finalize();
}// main
它似乎通过向量vec(100)
向量正常工作,抓取前二十个整数,下二十个,等等。但我认为它崩溃了,因为我一直在覆盖split_vec
中的元素,车库值使它崩溃。当我打印向量时,因为我在下面发送它,所以它是在崩溃之前打印的
0 64 0 33 0 1819240283 808662067 976302125 892679984 2121015 0 49 0 -773125744 32554 0 0 -773125760 32554 0 0
即使在vec
向量中没有0
或负数。因此,我试图通过添加split_vec.clear()来解决这个问题代码>代码,但这似乎也不起作用
下面是我用来编译和运行它的内容
mpic++ -std=c++11 prog.cpp -o prog.o
mpirun -np 6 prog.o // 5 slave process
要使MPI\u Recv()
成功,需要进行以下更改:
- 在您发布的代码中,
split_vec.size()
在MPI_Recv()
中为0,因为split_vec
尚未填充。因此,MPI_Recv()
将收到一条消息,但不会修改向量
- 必须首先分配接收缓冲区。在本例中,这意味着
split\u vec.reserve(split\u size)必须在调用MPI_Recv(&split_vec[0],MPI_INT,split_size,…)之前添加code>代码>。实际上,该方法将使向量的容量至少增加到n
个元素。正如@Zulan所注意到的,使用更为正确,因为它还更新了向量的大小
最后,下面的代码实现了这一点:
split_vec.resize(split_size);
MPI_Recv(&split_vec[0],MPI_INT,split_vec.size(),...);
这是一个正确的代码。请注意,必须修改用于填充秩0上的数组的索引。通过mpiCC main.cpp-o main-std=c++11-Wall编译它
#include <iostream>
#include <list>
#include "mpi.h"
#include <stdio.h>
#include <stdlib.h>
#include <vector>
#include <algorithm>
#include <map>
#include <random>
using namespace std;
int main(int argc, char **argv)
{
int rank, size, tag;
MPI_Status status;
vector<int> vec(100);
vector<int> split_vec;
MPI_Init(&argc, &argv);
MPI_Comm_size(MPI_COMM_WORLD, &size);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
tag=7;
random_device rd;
mt19937 gen(rd());
uniform_int_distribution<> dis;
generate(vec.begin(), vec.end(), [&](){ return dis(gen); });
// 100 ints / 5 slave processes
int split_size = vec.size() / size;
// split_size = size of vector of ints that each slave process should get
int offset = 0;
if (rank==0) {
// master process
for (int i=1; i<size; ++i){
split_vec.clear();
split_vec.reserve(split_size);
int j=0; // added j=0
while(j < split_size){
int elements = j + offset;
split_vec.push_back(vec[elements]);
j++;
}
//max = split_size;
offset = offset + split_size;
MPI_Send(&split_vec[0], split_vec.size(), MPI_INT, i, tag, MPI_COMM_WORLD);
}
}
else{
// slaves processes
split_vec.resize(split_size);
MPI_Recv(&split_vec[0], split_vec.size(), MPI_INT, 0, tag, MPI_COMM_WORLD, &status); // until receive is complete, split_vec.size()==0
}
MPI_Finalize();
}// main
您不能在此处使用std::vector::reserve
!虽然这不会崩溃,但在调用MPI\u Recv
/MPI\u Scatter
之后,向量的大小仍将为0!改为使用调整大小
。“发送的项目数量必须与接收的项目数量匹配”这是不正确的。标准(3.2.4)只要求:“接收消息的长度必须小于或等于接收缓冲区的长度。”@Zulan:谢谢你在我的回答中指出了这些错误!关于MPI,我还有很多东西要学。。。
#include <iostream>
#include <list>
#include "mpi.h"
#include <stdio.h>
#include <stdlib.h>
#include <vector>
#include <algorithm>
#include <map>
#include <random>
using namespace std;
int main(int argc, char **argv)
{
int rank, size, tag;
MPI_Status status;
vector<int> vec(100);
vector<int> split_vec;
MPI_Init(&argc, &argv);
MPI_Comm_size(MPI_COMM_WORLD, &size);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
tag=7;
random_device rd;
mt19937 gen(rd());
uniform_int_distribution<> dis;
generate(vec.begin(), vec.end(), [&](){ return dis(gen); });
// 100 ints / 5 slave processes
int split_size = vec.size() / size;
// split_size = size of vector of ints that each slave process should get
int offset = 0;
if (rank==0) {
// master process
for (int i=1; i<size; ++i){
split_vec.clear();
split_vec.reserve(split_size);
int j=0; // added j=0
while(j < split_size){
int elements = j + offset;
split_vec.push_back(vec[elements]);
j++;
}
//max = split_size;
offset = offset + split_size;
MPI_Send(&split_vec[0], split_vec.size(), MPI_INT, i, tag, MPI_COMM_WORLD);
}
}
else{
// slaves processes
split_vec.resize(split_size);
MPI_Recv(&split_vec[0], split_vec.size(), MPI_INT, 0, tag, MPI_COMM_WORLD, &status); // until receive is complete, split_vec.size()==0
}
MPI_Finalize();
}// main
#include <iostream>
#include <list>
#include "mpi.h"
#include <stdio.h>
#include <stdlib.h>
#include <vector>
#include <algorithm>
#include <map>
#include <random>
using namespace std;
int main(int argc, char **argv)
{
int rank, size;
vector<int> vec(100);
vector<int> split_vec;
MPI_Init(&argc, &argv);
MPI_Comm_size(MPI_COMM_WORLD, &size);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
random_device rd;
mt19937 gen(rd());
uniform_int_distribution<> dis;
generate(vec.begin(), vec.end(), [&](){ return dis(gen); });
// 100 ints / 5 slave processes
int split_size = vec.size() / size;
// split_size = size of vector of ints that each slave process should get
split_vec.resize(split_size);
MPI_Scatter(&vec[0],split_size,MPI_INT,&split_vec[0],split_size,MPI_INT,0,MPI_COMM_WORLD);
MPI_Finalize();
}// main