在MPI C中为每个进程生成随机数

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了在MPI C中为每个进程生成随机数相关的知识,希望对你有一定的参考价值。

我试图生成随机数,并在每个任务中将这些数字分配给数组。我想确保不同任务中的随机数不同。我怎么能实现这一目标?

如果每个MPI任务使用随机数(如我附加的代码)初始化自己的数组,那么这些数字在任务中是不同的吗?

我知道我可以生成一大组随机数并广播到每个任务,但这可能会导致大型数组的内存问题。

非常感谢您提供任何信息。

void initialize(float* inarray, int n){
    int i;
    for (i=0; i<n; i++){
            inarray[i] = random() / (float)RAND_MAX;
        }
    }
}

void main(int argc, char* argv[]){

    MPI_Comm comm=MPI_COMM_WORLD;
    int numnodes, myid, ierr;
    ierr=MPI_Init(&argc, &argv);
    ierr=MPI_Comm_size(comm, &numnodes);
    ierr=MPI_Comm_rank(comm, &myid);

    int n = 100;
    float *x = malloc(sizeof(float)*n);
    initialize(x, n);

    ierr=MPI_Finalize();
}
答案

这是我的愚蠢解决方案:在循环中,一个MPI任务创建随机数并按顺序发送到其他任务。对我来说,这就像手动播放,但节省了一点点内存。

    if (myid == 0){
        int i;
        for (i=0; i<n; i++){
            initialize(x, n);
            if (i != myid){
                MPI_Send(&x[0], n, MPI_FLOAT, i, 0, comm);
            }
        }
    }else{
        MPI_Recv(&x[0], n, MPI_FLOAT, 0, 0, comm, MPI_STATUS_IGNORE);
    }
另一答案

(伪)随机数发生器必须被播种,并且每个等级上有不同的种子。

在我的环境中(CentOS 7):

#include <stdio.h>
#include <stdlib.h>

#include <mpi.h>

int main(int argc, char *argv[]) {
    int rank;
    MPI_Init(&argc, &argv);
    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
    srand(rank+1);
    float f = (float)random() / (float)RAND_MAX;
    printf ("%d: %f\n", rank, f);
    MPI_Finalize();
    return 0;
}

产生

0: 0.840188
1: 0.700976
2: 0.561380
3: 0.916458
4: 0.274746
5: 0.135439
6: 0.486904
7: 0.352761
8: 0.206965
9: 0.565811
10: 0.926345
11: 0.785600
12: 0.632643
13: 0.999498
14: 0.354973
15: 0.215437
另一答案

事实上,这比预期的要复杂得多。有两个问题:

首先,假设您有40个mpi进程,所有进程都需要绘制10个数字,使用0和1之间的均匀分布。然后,如果您使用单个链条绘制400个数字,您将获得非常好的均匀分布。但如果你只抽出10个数字,你可能不会。从40链中拉出10个数字并不严格等同于从一个链中绘制400个数字。但是,只有当您需要对分发进行良好控制时,才会出现此问题。

其次,假设您希望以数字方式研究给定问题。你需要测试的是你的求解器的收敛。为此,您需要查看求解器在精细分辨率下是否表现良好。所以你需要的是以一种保持相同低频的方式产生不同的实现(你的随机数)(如果你想在傅立叶空间中)。要做到这一点,你需要确保在给定位置的随机数(比如400的327号)始终是相同的,无论你使用多少进程。

这两个问题都表明,从链中简单地绘制连续数字并不是一个好的解决方案。

所以你可以做的是: - 使用一个链 - 第一个过程使用链的前10个数。 - 第二个过程使用链的第11到第20个数字。 ......

但这意味着给定的过程必须丢弃链中给定数量的元素。如果使用“通常”随机数生成器,则丢弃n数是O(n)运算。这意味着您无法并行化您的问题。你需要的是使用一个随机生成器,它包含一个方法来丢弃O(1)中的n个绘制。你可以在网上找到很多这样的方法。或者你可以自己编码(但这真的是试图重新发明轮子)。

我自己使用:https://rdrr.io/cran/sitmo/ 但是它适用于C ++,但是你可以确定你可以找到C版或者只使用C ++实现这一部分的版本......

以上是关于在MPI C中为每个进程生成随机数的主要内容,如果未能解决你的问题,请参考以下文章

MPI:rand() 在每次运行中为所有进程提供相同的常数

在 MPI 和 C 中,如何将结构信息的结构发送到从属进程并接收它们?

mpi 进程在信号 11 上退出

打开 MPI Waitall() 分段错误

使用 MPI 分配进程

mpi生成随机数组并进行排序