MPI从双数组计算差异符号

Posted

技术标签:

【中文标题】MPI从双数组计算差异符号【英文标题】:MPI calculate difference sign from double array 【发布时间】:2019-06-09 18:32:55 【问题描述】:

我正在尝试使用 MPI 计算双数组的差异符号,无需使用外部行或列,结果可能如下所示:

在数组中

1 0 1 1 1

2 1 3 1 4

1 3 1 0 1

2 1 -1 1 2

输出数组

0 0 0 0 0

0 -1 0 -1 0

0 1 -1 1 0

0 0 0 0 0

我编写了一些代码,但是当我尝试将 b 数组写入控制台时,我收到了访问冲突读取位置错误。我是 MPI 的新手,我不知道这段代码是否正确。任何想法如何让它工作?

#include <iostream>
#include <chrono>
#include <mpi.h>
#include <iomanip>
#include <cstdlib>

using namespace std;
int main(int argc, char *argv[])


int size, rank;
MPI_Init(&argc, &argv);
MPI_Comm_size(MPI_COMM_WORLD, &size);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);

srand(time(NULL));

int R = 4;
int C = 8;


int **a = new int *[R];
a = new int *[R]; 
a[0] = new int[R*C];
for (int i = 1; i < R; i++)

    a[i] = &a[0][i*C];


if (rank == 0) 
    for (int i = 0; i < R; i++)
    
        for (int j = 0; j < C; j++) 
        
            a[i][j] = (rand() % 10) - 5;
            cout << setw(5) << a[i][j] << " ";
        
        cout << endl;
    




int **b = new int *[R];
b = new int *[R]; 
b[0] = new int[R*C];
for (int i = 1; i < R; i++)

    b[i] = &b[0][i*C];



MPI_Bcast(a, R*C, MPI_INT, 0, MPI_COMM_WORLD);
MPI_Barrier(MPI_COMM_WORLD);

int partR = R / size;
int partC = C / size;
int part = partR * partC*size; 

int *c = new int[part];

int sumF = 0;
int sumS = 0;
int tmp = 0;
int x = 0;

auto start = chrono::high_resolution_clock::now();

for (int i = rank*partR; i <= rank*partR+partR; i++) 
    for (int j = rank*partC; j <= rank*partC + partC; j++) 
        if (i != 0 && i != R - 1 && j != 0 && j != C - 1) 
            sumF = a[i - 1][j - 1] + a[i + 1][j - 1] + a[i - 1][j + 1] + a[i + 1][j + 1];
            sumS = a[i - 1][j] + a[i + 1][j] + a[i][j - 1] + a[i][j + 1];
            if ((sumF - sumS) > 0)
                tmp = 1;
            if ((sumF - sumS) < 0)
                tmp = -1;
            if ((sumF - sumS) == 0)
                tmp = 0;
            c[x] = tmp;
            x++;
        
    


MPI_Gather(c, part, MPI_INT, &(b[0][0]), part, MPI_INT, 0, MPI_COMM_WORLD);


auto finish = chrono::high_resolution_clock::now();

chrono::duration<double> elapsed = finish - start;

if (rank == 0) 
    cout << endl << "Result: " << endl;
    for (int i = 0; i < R; i++) 
        for (int j = 0; j < C; j++) 
            cout << b[i][j] << " ";
        
        cout << endl;
    

    cout << endl << "T: " << elapsed.count() << endl;



MPI_Finalize();
return 0;
system("PAUSE");

【问题讨论】:

您正在向另一个进程发送一个指针数组。指针指向进程的地址空间,因此它们不能在另一个进程地址空间中有效。 【参考方案1】:
MPI_Bcast(a, R*C, MPI_INT, 0, MPI_COMM_WORLD);

这不是在广播 2D 数组。这需要int**,将其转换为void*,然后告诉编译器它包含R*C 整数。它没有。它包含子数组的地址。

在未来的重构中改用一维数组。没有间接的一维访问更好。

但现在要解决您的问题:

MPI_Bcast(a[0], R*C, MPI_INT, 0, MPI_COMM_WORLD);

【讨论】:

谢谢,你是对的,但它应该是 a[0] 还是 a[0][0] 因为它是第一个元素。无论如何,即使我修复它,同样的异常仍然会发生。 可以是a[0]&amp;a[0][0]。收集的发送计数应为 part / size @folk 是在 MPI 调用期间还是在其他地方? @GillesGouaillardet 为什么除以size 感谢重播,我认为它应该只是部分而不是部分/大小,因为我将整个 c 数组从每个线程获取到 b 数组。我用 recv 指针修复了我的 Gather 函数并正确初始化了 c 数组。但是当我在 4 个线程上运行它时仍然会出现访问冲突,我不确定它在哪里,因为我无法在 4 个线程上进行调试,但它在大 dobule /for/ 块中的某个地方。暂时没有想法。明天检查。

以上是关于MPI从双数组计算差异符号的主要内容,如果未能解决你的问题,请参考以下文章

使用 MPI_Bcast 时出现 MPI 分段错误

MPI_Allgather 与 2D 数组

在c ++中从双精度转换为字符串[重复]

使用 MPI 发送二维数组

通过 MPI 发送和接收二维数组

带有 MPI 的 C 中的结构数组