时间随着线程数的增加而增加

时间:2020-07-24 15:46:57

标签: c parallel-processing

我试图计算用于矩阵加法的加速和最佳线程数,但是并行执行总是比顺序执行花费更多时间,并且增加持续增加直到大约8个线程,然后变成某种常数。谁能帮我找出原因?

顺序代码:

#include <stdlib.h>    
#include <stdio.h>     
#include <time.h>  
 
 
int main (int argc, char *argv[])  
{ 
 
    int ARRAY_SIZE;     
    int n = 10000;                  
    int n_per_thread;                     
    int i,j;       
    int *a[n];
    int *b[n]; 
    int *c[n];  
    for (i=0; i<n; i++){
         a[i] = (int *)malloc(n * sizeof(int)); 
         b[i] = (int *)malloc(n * sizeof(int));
         c[i] = (int *)malloc(n * sizeof(int)); 
    }     
    for(i=0; i<n; i++) {
        for(j=0;j<n;j++){ 
        a[i][j] = 1;
      } 
    } 
    for(i=0; i<n; i++) {
        for(j=0;j<n;j++){ 
        b[i][j] = 1;
      } 
    }    
    clock_t t;  
    t = clock();  
    for(i=0; i<n; i++) {
        for(j=0;j<n;j++){ 
        c[i][j] = a[i][j]+b[i][j];
      } 
    }
    t = clock() - t;  
    double time_taken = ((double)t)/CLOCKS_PER_SEC; 
    printf("Time taken by sequential for matrix size %d: ",n); 
    printf("%f%s\n",time_taken," seconds"); 
    return 0; 
} 

并行代码:

#include <stdlib.h>    
#include <stdio.h>     
#include <omp.h>       
#include <time.h>  
 
#define NUM_THREADS 10  
 
int main (int argc, char *argv[])  
{ 
 
    int ARRAY_SIZE; 
    int n = 10000;           
    int n_per_thread;                    
    int total_threads = NUM_THREADS;       
    int i,j;       
    int *a[n];
    int *b[n]; 
    int *c[n];  
    for (i=0; i<n; i++){
         a[i] = (int *)malloc(n * sizeof(int)); 
         b[i] = (int *)malloc(n * sizeof(int));
         c[i] = (int *)malloc(n * sizeof(int)); 
    }     
    for(i=0; i<n; i++) {
        for(j=0;j<n;j++){ 
        a[i][j] = 1;
      } 
    } 
    for(i=0; i<n; i++) {
        for(j=0;j<n;j++){ 
        b[i][j] = 1;
    }
    }          
    omp_set_num_threads(total_threads); 
    n_per_thread = n/total_threads; 
    clock_t t;  
    t = clock();  
    #pragma omp parallel for shared(a, b, c) private(i) schedule(static, n_per_thread) 
        for(i=0; i<n; i++) {
            for(j=0;j<n;j++){ 
                c[i][j] = a[i][j]+b[i][j];
      } 
    }
    t = clock() - t;  
    double time_taken = ((double)t)/CLOCKS_PER_SEC; 
    printf("Time taken by parallel for vector size %d: ",n); 
    printf("%f%s\n",time_taken," seconds"); 
    return 0; 
} 


 

1 个答案:

答案 0 :(得分:1)

多线程处理无济于事的原因可能是因为bottlenecked是内存带宽而不是CPU速度。

现代台式计算机的内存带宽约为20 GB / s。假设sizeof(int) == 4,这意味着每秒可以在内存中传输50亿个整数。由于您的每个算术运算均读取2个整数并写入1,因此这意味着现代台式机具有足够的内存带宽,每秒可完成这些算术运算的1.7十亿。因此,现代台式计算机具有足够的内存带宽,可以在一秒钟内用n = 40000运行程序。

除非您使用的是NUMA架构,否则使用多线程只会增加潜在的计算速度,但不会增加您的内存带宽。

循环代码的单线程版本可能已经由编译器获取了vectorized,这意味着它使用了SIMD指令。至少在激活编译器优化的情况下编译单线程代码时,编译器会这样做。这样,单线程版本的代码已经在很大程度上并行化了。

使用多线程处理当然可以使代码进一步并行化。但是您的计算非常简单,因为您只对每条数据执行一次加法。因此,您的矢量化单线程版本可能不是因为CPU的计算能力而是因为您的内存带宽而成为瓶颈。请参阅以下StackOverflow问题,以获取更多信息,如果循环的矢量化由于内存带宽而受到瓶颈的影响,则有时如何无法为您带来性能上的好处:

Why vectorizing the loop does not have performance improvement

如果您的计算是如此简单,以至于代码的单线程(矢量化)版本都因内存带宽而不是CPU速度而成为瓶颈,那么通过引入多线程来增加更多的计算能力将不会带来太大收益。