簡體   English   中英

OpenMP 矩陣乘法花費的時間比預期的要長

[英]OpenMP matrix multiplication takes more time than expected

我正在編寫一個 OpenMP 程序來將兩個矩陣相乘。 這個想法是每個線程計算每個單元格結果的一部分。 然后,在那之后,我為每個單元格添加這些結果以獲得乘法結果。

問題是,當我使用大型矩陣(512x512 或 1024x1024)時,該程序需要很長時間。 實際上,當我使用 5 個線程使用大小為 1024x1024 的矩陣時,需要 43 秒,而使用 1 個線程則需要 14 秒。

我在想這可能是導致巨大延遲的關鍵部分。

這是代碼:

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

int ** make_array(int n,int m,int f)
{
    int i,j;
    int *linear, **arr;
    linear = malloc(sizeof(int)*m*n);
    arr = malloc(sizeof(int *)*n);
    for(i = 0;i<n;++i) arr[i] = &linear[i*m];
    if(f == 0)
    {
        for(i=0;i<n;++i)
        for(j=0;j<m;++j) arr[i][j] = 0;
        return arr;
    }
    for(i=0;i<n;++i)
        for(j=0;j<m;++j) arr[i][j] = 1+i;
    return arr;
}

void printMat(int **mat, int n)
{
    int i,j;
    for(i = 0; i < n; ++i)
    {
        for(j = 0; j < n;++j)
        {
            printf("%d ",mat[i][j]);
        }
        printf("\n");
    }
}

int main (int argc, char *argv[])
{
    int n;            /// matrix dimension


    scanf("%d", &n);
    double TIME = 0;
    int **a,**b,**c;
    a = make_array(n,n,1);
    b = make_array(n,n,1);
    c = make_array(n,n,0);

    int i,j,k;

    #pragma omp parallel private(i,j,k) shared(a,b,c,TIME)
    {
        double start = omp_get_wtime();
        int **local;
        local = make_array(n,n,0);
        for(i = 0; i < n; ++i)
        {
            for(j = 0; j <n; ++j)
            {
                local[i][j] = 0;
                #pragma omp for schedule(static)
                for(k = 0; k < n; ++k)
                {
                    local[i][j]+= a[i][k] * b[k][j];
                }
            }
        }
        for(i = 0; i <n;++i)
        {
            for(j = 0; j < n; ++j)
            {
                #pragma omp critical
                c[i][j] += local[i][j];
            }
        }
        double end = omp_get_wtime();
        if(TIME < end - start)
        {
            #pragma omp critical
            TIME = end - start;
        }
    }

    printf("%f \n", TIME);
}

任何幫助將非常感激。

這段代碼有很多問題

並行化方法效率很低

對於每個可能的ij ,您將一個非常小的工作共享給多個線程。 此外,在並行 for 循環的末尾有一個隱式障礙 因此,線程之間的通信可能比實際計算花費更多的時間。

臨界區通常很慢(通常使用鎖來實現)。 在這里,您可以用原子操作替換它。

使用 k 個線程,代碼需要 k 次更多 memory 並且很可能是 memory 綁定的(因為緩存和要填充的更多數據,更不用說現在昂貴的額外頁面錯誤)。

因此,您需要重新設計並行化方法 例如,您可以在基於i的循環上移動#pragma omp for schedule(static) 或者,您可以將矩陣分成並在線程之間共享工作。

請使用BLAS庫進行矩陣乘法。 它們比這段代碼優化得多。

以下是一些其他問題的列表:

  • 有 memory 泄漏(有malloc但沒有free的)。
  • 基於TIME的條件存在競爭條件。
  • 與平坦的 arrays 相比,這里的鋸齒狀陣列可能效率低下。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM