繁体   English   中英

OpenMP 矩阵乘法问题

[英]OpenMP Matrix Multiplication Issues

我正在尝试乘以矩阵的值。

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

#define N 2048
#define FactorIntToDouble 1.1; 
#define THREAD_NUM 4

double firstMatrix [N] [N] = {0.0};
double secondMatrix [N] [N] = {0.0};
double matrixMultiResult [N] [N] = {0.0};

// Sync
void matrixMulti() {
    for(int row = 0 ; row < N ; row++){
        for(int col = 0; col < N ; col++){
            double resultValue = 0;
            for(int transNumber = 0 ; transNumber < N ; transNumber++) {
                resultValue += firstMatrix [row] [transNumber] * secondMatrix [transNumber] [col] ;
            }

            matrixMultiResult [row] [col] = resultValue;
        
        }
    }
}


void matrixInit() {
    for(int row = 0 ; row < N ; row++ ) {
        for(int col = 0 ; col < N ;col++){
            srand(row+col);
            firstMatrix [row] [col] = ( rand() % 10 ) * FactorIntToDouble;
            secondMatrix [row] [col] = ( rand() % 10 ) * FactorIntToDouble;
        }
    }
    
}

// Parallel
void matrixMulti2(int start, int end) {
    printf("Op: %d - %d\n", start, end);
    for(int row = start ; row < end ; row++){
        for(int col = 0; col < N ; col++){
            double resultValue = 0;
            for(int transNumber = 0 ; transNumber < N ; transNumber++) {
                resultValue += firstMatrix [row] [transNumber] * secondMatrix [transNumber] [col] ;
            }

            matrixMultiResult [row] [col] = resultValue;
        }
    }
}


void process1(){
    clock_t t1 = clock(); 
    #pragma omp parallel
    {
    int thread = omp_get_thread_num();
    int thread_multi = N / 4;
    
    int start = (thread) * thread_multi;
        
        int end = 0;
        if(thread == (THREAD_NUM - 1)){
            end = (start + thread_multi);
        }else{
            end = (start + thread_multi) - 1;
        }
        
        matrixMulti2(start, end);
        
    
    }
    
    clock_t t2 = clock(); 
    printf("time 2: %ld\n", t2-t1);
}


int main(){
    matrixInit();
    
    clock_t t1 = clock(); 
    matrixMulti();
    
    clock_t t2 = clock(); 
    printf("time: %ld", t2-t1);
    
    process1();

    return 0;
}

我有并行和同步版本。 但是并行版本比同步版本长。

当前同步需要大约 90 秒,并行需要 100 秒。这对我来说没有意义。

我的逻辑是将矩阵从前 4 个语句分成 4 个部分。 我认为这是合乎逻辑的。

在我完成这部分之后。 我想弄清楚如何进一步加快并行进程。 可能使用施特拉森的矩阵乘法。 我只是不知道从哪里开始或如何达到这一点。

我已经花了大约 5 个小时试图弄清楚这一点。

这里是:

// Sync
void matrixMulti() {
    #pragma omp parallel for collapse(2)
    for(int row = 0 ; row < N ; row++){
        for(int col = 0; col < N ; col++){
            double resultValue = 0;
            for(int transNumber = 0 ; transNumber < N ; transNumber++) {
                resultValue += firstMatrix [row] [transNumber] * secondMatrix [transNumber] [col] ;
            }

            matrixMultiResult [row] [col] = resultValue;
        
        }
    }
}

更新:这是我使用 gcc 10.3 -O3 -fopenmp 标志在 8 核系统上得到的结果(我向您展示了程序的输出和 linux time 命令的结果):

main()已更改为使用omp_get_wtime()测量时间,因为在 linux clock()测量处理器时间:

double t1 = omp_get_wtime(); 
matrixMulti();    
double t2 = omp_get_wtime(); 
printf("time: %f", t2-t1);

串行程序:

time: 25.895234

real    0m33.296s
user    0m33.139s
sys     0m0.152s

使用: #pragma omp parallel for

 time: 3.573521

 real    0m11.120s
 user    0m32.205s
 sys     0m0.136s

使用: #pragma omp parallel for collapse(2)

time: 5.466674

real    0m12.786s
user    0m49.978s
sys     0m0.248s

结果表明矩阵的初始化需要大约。 8 s,因此它也可能值得并行化。 没有collapse(2)程序运行得更快,所以不要使用collapse(2)子句。 请注意,在您的系统上,根据您的硬件,您可能会获得不同的速度提高甚至降低。 矩阵乘法的速度很大程度上取决于内存读/写的速度。 共享内存多核系统(即大多数 PC、笔记本电脑)在并行化该程序时可能不会显示任何速度提升,但分布式内存多核系统(即高端服务)肯定会显示性能提升。 有关更多详细信息,请阅读例如这个

更新 2:在 Ryzen 7 5800X 上,我得到了41.6 s1.68 s ,这比内核数量的增加更大。 这是因为当所有内核都被使用时,有更多的缓存可用。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM