📜  SIMD和MIMD之间的区别(1)

📅  最后修改于: 2023-12-03 15:20:08.722000             🧑  作者: Mango

SIMD和MIMD之间的区别

SIMD和MIMD都是并行计算的形式,但它们之间有明显的区别:SIMD是单指令多数据流的并行计算,而MIMD是多指令多数据流的并行计算。

1. SIMD(Single Instruction Multiple Data Stream)

在SIMD中,多个处理器同时执行相同的指令,但每个处理器都能够处理不同的数据流。这种方法特别适用于处理大量的数据集合。例如,当你需要对整个数组进行相同的操作时,你可以使用SIMD来同时处理所有元素,而不需要分别操作每一个元素。

// 使用SIMD求和
#include <immintrin.h>
#include <cstdio>
int main(){
    float a[8] = {1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0};
    __m256 sum = _mm256_set_ps(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f);
    for(int i=0; i<8; i+=8){
        __m256 avx = _mm256_loadu_ps(&a[i]);
        sum = _mm256_add_ps(sum, avx);
    }
    
    float ans[8] = {0.0f};
    _mm256_storeu_ps(ans, sum);
    printf("%f\n", ans[0]+ans[1]+ans[2]+ans[3]+ans[4]+ans[5]+ans[6]+ans[7]);  // 36
    return 0;
}

在上面的例子中,我们使用了AVX指令集来创建一个__m256类型的变量sum,用于存储结果。然后我们将所有的数据分组成了大小为8的小块,一个__m256类型的变量可以存储8个4字节的单精度浮点数。接着我们循环处理每一个小块,并将所有块的和存储在sum中。最后我们将包含每个小块的和的数组ans加起来输出。

2. MIMD(Multiple Instruction Multiple Data Stream)

MIMD是一种不同的并行计算形式,它允许不同的处理器同时执行不同的指令和数据。这种方法特别适用于解决不同类型的任务或处理不同类型的数据。

// 使用MPI进行并行计算
#include <mpi.h>
#include <cstdio>
#include <cstdlib>
int main(int argc, char *argv[]){
    int rank, size, tag = 0;
    MPI_Status status;
    MPI_Init(&argc, &argv);
    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
    MPI_Comm_size(MPI_COMM_WORLD, &size);

    int n = 10;
    int m = n / size;
    int *a = new int[n];
    int *b = new int[m];
    int c = 0;
    if(rank == 0){
        for(int i=0; i<n; i++)
            a[i] = i+1;
    }
    MPI_Scatter(a, m, MPI_INT, b, m, MPI_INT, 0, MPI_COMM_WORLD);
    for(int i=0; i<m; i++)
        c += b[i];
    int sum = 0;
    MPI_Reduce(&c, &sum, 1, MPI_INT, MPI_SUM, 0, MPI_COMM_WORLD);
    if(rank == 0)
        printf("%d\n", sum);    // 55
    MPI_Finalize();
    return 0;
}

在上面的例子中,我们使用MPI(Message Passing Interface)来实现MIMD并行计算。首先,我们使用MPI_Init函数初始化MPI环境,并通过MPI_Comm_rank和MPI_Comm_size函数获取当前处理器的rank和总数size。然后我们创建一个大小为n的数组a,并将它分割成大小为m的小块,m是进程数。我们使用MPI_Scatter将每个小块分配给不同的进程。接着每个进程执行自己的计算,计算小块的和。最后我们使用MPI_Reduce将每个进程的结果相加,得到最终的结果。

这里需要注意的是,虽然MIMD可以执行不同的指令和数据,但每个进程仍然需要遵守同样的算法和流程,否则很容易出现并发控制问题。此外,MIMD的开销也比SIMD大,因为需要进行数据交换和处理。