我的代码要求3个进程生成如下所示的2D向量(在第二列上递增0.05),属于其他进程的行的值为零(未显示):
Proc 1
100,0,1,1,1
100,0.05,4,1,5
100,0.10,10,5,11
100,...,...,...,...
100,0.30,12,11,15
Proc 2
100,0.35,40,35,55
100,0.40,45,39,55
100,...,...,...,...
100,0.65,180,90,215
Proc 3
100,0.70,130,67,145
100,...,...,...,...
100,1.0,1,1,1
我尝试使用MPI_Allreduce生成一个相同大小的2D向量:
100,0,1,1,1
100,0.05,2,2,3
100,0.1,3,2,4
100,0.15,3,2,6
100,0.2,4,2,6
100,0.25,14,10,20
100,0.30,15,11,21
100,0.35,10,6,19
100,0.4,13,9,21
100,0.45,16,12,25
100,0.5,33,17,55
100,0.55,70,33,155
100,0.6,80,30,190
100,0.65,110,45,200
100,0.7,145,134,161
100,0.75,131,127,138
100,0.8,123,120,129
100,0.85,117,114,122
100,0.9,111,111,113
100,0.95,110,108,112
100,1.0,1,1,1
到目前为止,我已经尝试了以下方法:
// Function that calculates the average number of steps, incrementing over arraysize and probability
// Output vector has 21 rows and columns represent [Arraysize, Probability, Average, Min Value, Max Value]
std::vector<std::vector<double>> forest_fire_average_steps(int arraySize, int numberOfRuns, int rank, int numProcs)
{
int count = 21 / numProcs;
int start = rank * count;
int end = start + count;
// init probability
double p;
// Create empty vector to store results
std::vector<std::vector<double>> stepsResults(21, std::vector<double>(5, 0));
if (rank == 0) p = 0;
if (rank == 1) p = 0.35;
if (rank == 2) p = 0.7;
if (rank < 3)
{
// Iterates over a range of probability values, from 0 to 1 in 0.05 increments.
for (int i = start; i < end; ++i)
{
// Adds the array size and probability value to the first two columns of the row.
stepsResults[i][0] = arraySize;
stepsResults[i][1] = p;
// Runs the forest fire model 'numberOfRuns' times with a defined array size and p
// and stores the results.
std::vector<double> runSteps;
for (int j = 0; j < numberOfRuns; ++j)
{
runSteps.push_back(forest_fire(arraySize, p).stepCount);
}
// Sums the runSteps vector.
// Could have used std::reduce which is more efficient but the HPC G++ compiler was out of date.
int sum = 0;
for (auto& n : runSteps)
{
sum += n;
}
// Calculates and stores the average of the results.
double averageSteps = sum / runSteps.size();
stepsResults[i][2] = averageSteps;
stepsResults[i][3] = *min_element(runSteps.begin(), runSteps.end());
stepsResults[i][4] = *max_element(runSteps.begin(), runSteps.end());
// Increments probability.
p += 0.05;
}
}
std::vector<std::vector<double>> finalResults(21, std::vector<double>(5, 0));
for (unsigned int i=0;i<21;++i){
int ierr = MPI_Allreduce(stepsResults[i].data(), finalResults[i].data(), 5, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
}
MPI_Finalize();
if (rank == 3)
{
for (int i = 0; i < 21; i++)
{
for (int j = 0; j < finalResults[i].size(); j++)
{
if (j < 4)
{
std::cout << finalResults[i][j] << ",";
} else
{
std::cout << finalResults[i][j];
}
}
std::cout << std::endl;
}
}
return finalResults;
}
我不完全确定为什么,但输出看起来像这样,其中它明显跳过了一些行(0.6、0.65等),并添加了额外的零行:
100,0,1,1,1
100,0.05,2,2,3
100,0.1,3,2,4
100,0.15,3,2,6
100,0.2,4,2,6
100,0.35,10,6,19
100,0.4,13,9,21
100,0.45,16,12,25
100,0.5,33,17,55
100,0.55,70,33,155
100,0.7,145,134,161
100,0.75,131,127,138
100,0.8,123,120,129
100,0.85,117,114,122
100,0.9,111,111,113
0,0,0,0,0
0,0,0,0,0
0,0,0,0,0
0,0,0,0,0
0,0,0,0,0
0,0,0,0,0
我的实现是否存在导致此问题的错误?
1条答案
按热度按时间tcbh2hod1#
我很惊讶这个程序没有因为segfault而中止。你的问题在于你把矩阵定义为
vector<vector<double>>
。MPI需要连续的缓冲区,而向量的向量是一堆小数组,随机分散在内存中。为你的对象写一个类,让它存储一个vector<double>
,在其中你用i+j*N
左右的索引。