矩阵乘法优化 (OpenMP) - C

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

我正在学习一些有关 openMP 的知识,并尝试在这里使用它来将两个矩阵相乘。

void matrix_multiply(matrix *A, matrix *B, matrix *C) {

    #pragma omp parallel
    {
        #pragma omp for 
        for(int i = 0; i < A->dim.rows; i++) {
            for(int j = 0; j < B->dim.cols; j++) {
                C->data[i][j] = 0;
                for (int k = 0; k < A->dim.cols; k++) {
                C->data[i][j] += A->data[i][k] * B->data[k][j];
               }
           }
       }
   }
}

typedef struct shape {
    int rows;
    int cols;
} shape;

typedef struct matrix {
    shape dim;
    float** data;
} matrix;

对此仍然有点陌生,那么是否有任何简单的更改可以提高性能或者我已经做到了?另外,我是否会因不使用缩减而遇到任何数据竞争?

c matrix openmp
2个回答
2
投票

您当前的实现可能无法改进太多。此时就取决于编译器和缓存的使用情况。 Intel 提出了一个有趣的观点:GCC 需要交换两个循环才能向量化乘法(即使用 SIMD)。对于非常大的矩阵,您可能会考虑将矩阵划分为块而不是条带。这会带来复杂性和开销,但可以提高缓存使用率。 仅当您使用多个线程对单个变量求和时才需要归约子句,但这里的情况并非如此,因为您只对

k

求和。


最后(但这完全是个人的)请注意,您可以将这两个指令替换为一个指令

#pragma omp parallel for

在我看来看起来更干净。


0
投票

利用 SIMD,它现在随 OpenMP 一起提供(检查编译器可用性 - 并非所有编译器都提供 SIMD)。你可以这样实现:

#pragma omp parallel for for(int i = 0; i < A->dim.rows; i++) { for(int j = 0; j < B->dim.cols; j++) { C->data[i][j] = 0; #pragma omp simd for (int k = 0; k < A->dim.cols; k++) { C->data[i][j] += A->data[i][k] * B->data[k][j]; } } }

考虑连续内存分配的影响及其对 SIMD 指令和访问速度的影响。通常,这使得 SIMD 操作“行快”而“列慢”。这应该会影响您分配内存的方式。
© www.soinside.com 2019 - 2024. All rights reserved.