我如何在单个功能上应用MPI

问题描述 投票:2回答:1

我需要在我的代码中在两个CPU上并行运行函数generator。该项目有两个文件main.ccartes.c,并且它是按顺序运行的。

main.c文件包含一个for循环,该循环调用函数generator

main.c

MPI_Init(&argc, &argv);
int id;
MPI_Comm_rank(MPI_COMM_WORLD, &id);
.
.
.
for (iter_sec = 0; iter_sec < long_of_seq; iter_sec++) { //
    uint64_t Xg1 = generator(&K[0], iter_sec, ratio1, ratio2, ratio3, ratio4, m1, m2, id);
    sequence[iter_sec] = Xg1;
    .
    .
}
useTheSequenceArrayResultFromTheForLoopToCaclulateAndPrintTheFinalResult(sequence);
.
.
.

cartes.c文件包含generator功能

cartes.h

uint64_t generator (key *K,int iter_sec,double  ratio1, double  ratio2,double ratio3, double ratio4,uint64_t m1, uint64_t m2, int id);

cartes.c

.
.
.
uint64_t generator(key* K, int iter_sec, double ratio1, double ratio2, double ratio3, double ratio4, uint64_t m1, uint64_t m2, int id){
    K->X_s = someFunction(...);
    K->X_s = someOtherFunction(...);

    Xresult = K->X_p ^ K->X_s;
    return Xresult;
}
.
.
.

我正在尝试在两个CPU上计算函数generator的结果。我将处理器的等级ID传递给函数generator。如果等级ID为0,我需要致电someFunction,如果等级为1,我需要致电someOtherFunction。最后,我需要从^someFunction返回结果的XOR someOtherFunction

我试图做的是这个:

.
.
.
uint64_t generator(key* K, int iter_sec, double ratio1, double ratio2, double ratio3, double ratio4, uint64_t m1, uint64_t m2, int id){
    if (id == 0) {
        K->X_s = someFunction(...);
    }
    else if(id == 1){
        K->X_s = someOtherFunction(...);
    }

    Xresult = K->X_p ^ K->X_s;
    return Xresult;
}
.
.
.

但是上面修改的功能不起作用。

当我尝试运行代码时:

mpicc main.c -o saving
mpirun -np 4 ./saving

整个代码运行四次,generator的结果不会返回到for循环,也不会存储在sequence数组中。

[我该如何修改sequence函数,使其在不同的CPU上执行someFunctionsomeOtherFunction,并将它们的XOR结果返回到主文件中的for loop?填充sequence数组后,我将其传递给函数useTheSequenceArrayResultFromTheForLoopToCaclulateAndPrintTheFinalResult以计算最终结果。

c mpi
1个回答
1
投票

您并行运行程序的四个实例,但是您忘记了使用MPI_Reduce(...)将所有结果收集在一个位置。您可以在下面看到一个有关如何执行此操作的小示例。但是您必须决定需要在哪里收集结果。您可以在任何地方收集它们,但是出于性能原因,最好在循环之外收集它们。

#include <stdio.h>
#include <mpi.h>

#define RESULT_1 0x55
#define RESULT_2 0xAA
#define UNDEFINED 0xBB

int calc(int id) {
    if (id == 0) {
        return RESULT_1;
    }
    return RESULT_2;
}

int main (int argc, char* argv[])
{
    int id, local, global = UNDEFINED;

    MPI_Init (&argc, &argv);
    MPI_Comm_rank (MPI_COMM_WORLD, &id);

    local = calc(id);

    MPI_Reduce(&local, &global, 1, MPI_INT, MPI_BXOR, 0, MPI_COMM_WORLD);

    printf("at the moment: local=%02x, global=%02x\n", local, global);

    if (!id) {
        printf("Result is: %02x\n", global);
    }

    MPI_Finalize();
    return 0;
}

UPDATE#1

当使用参数mpirun运行-np 4时,将获得程序的4个实例并行运行。如果您的计算机有4个核心,则每个实例的变量id都会获得不同的值。

您可以使用任何变量或数组进行任何操作。但是您应该记住,所有实例都有独立的变量集。一个实例不能访问另一个实例的变量。]​​>

您可以调用MPI_Reduce()将来自不同实例的变量或数组的值组合为单个变量或数组。第一个参数是指向源的指针。第二个是指向目标的指针。

仅具有id == 0的实例将获得结果。因此,如果您打算打印或使用结果,则必须使用id == 0在实例内部进行处理。

这里是为数组而不是变量重写的同一示例。

#include <stdio.h>
#include <mpi.h>

#define SIZE_OF_ARRAY 16

#define RESULT_1 0x55
#define RESULT_2 0xAA
#define UNDEFINED 0xBB

int calc(int id) {
    if (id == 0) {
        return RESULT_1;
    }
    return RESULT_2;
}

int main (int argc, char* argv[])
{
    int i, id;
    static int local[SIZE_OF_ARRAY];
    static int global[SIZE_OF_ARRAY];

    MPI_Init (&argc, &argv);
    MPI_Comm_rank (MPI_COMM_WORLD, &id);

    for(i = 0; i < SIZE_OF_ARRAY; i++) {
        local[i] = calc(id);   
        global[i] = UNDEFINED; // just to show that this value will be altered
    }

    // for an instance with (id == 0), local elements will have a value of 0x55
    // for an instance with (id != 0), local elements will have a value of 0xAA
    // the value of elements of global is undefined here

    MPI_Reduce(local, global, SIZE_OF_ARRAY, MPI_INT, MPI_BXOR, 0, MPI_COMM_WORLD);

    // after this call the values of elements of global are undefined if (id != 0)
    // if (id == 0) the values of elements of global will be combination of
    // appropriate elements of local arrays from different instances
    // let's denote "var_0" the variable "var" from the instance #0
    // we will get:
    // global_0[i] = local_0[i] ^ local_1[i] ^ local_2[i] ^ local_3[i]

    if (!id) {
        // use the sequence array result from the loop here
        printf("Result is: [%02x", global[0]);
        for(i = 1; i < SIZE_OF_ARRAY; i++) {
            printf(", %02x", global[i]);
        }
        printf(" ]\n");
    }

    MPI_Finalize();
    return 0;
}
© www.soinside.com 2019 - 2024. All rights reserved.