C语言中的并行程序设计

C语言中的并行程序设计,c,parallel-processing,C,Parallel Processing,我试图在C中并行化光线跟踪器,但执行时间不会随着线程数量的增加而减少。到目前为止,我掌握的代码是: main2(thread function): float **result=malloc(width * sizeof(float*)); int count=0; for (int px=0;, px<width; ++px) { ... for (int py=0; py<height; ++py) { ...

我试图在C中并行化光线跟踪器,但执行时间不会随着线程数量的增加而减少。到目前为止,我掌握的代码是:

main2(thread function):

float **result=malloc(width * sizeof(float*));
int count=0;
for (int px=0;, px<width; ++px)
{
     ...
     for (int py=0; py<height; ++py)
     {
         ...
         float *scaled_color=malloc(3*sizeof(float));
         scaled_color[0]=...
         scaled_color[1]=...
         scaled_color[2]=...

         result[count]=scaled_color;
         count++;
         ...
      }
}
...
return (void *) result;

main:
pthread_t threads[nthreads];
 for (i=0;i<nthreads;i++)
 {
      pthread_create(&threads[i], NULL, main2, &i);
 }

 float** result_handler;

 for (i=0; i<nthreads; i++)
 {
      pthread_join(threads[i], (void *) &result_handler);
      int count=0;

      for(j=0; j<width;j++)
     {
          for(k=0;k<height;k++)
          {
               float* scaled_color=result_handler[count];
               count ++;
               printf...
           }
           printf("\n");
       }
  }
main2(线程函数):
浮动**结果=malloc(宽度*尺寸)(浮动*);
整数计数=0;

对于(int px=0;,px仅添加线程是不够的,您还需要实际拆分任务。看起来您在每个线程中都在做相同的工作,因此您可以使用n个线程获得结果的n个副本。

仅添加线程是不够的,您还需要实际拆分任务。看起来您在每个线程中都在做相同的工作,因此您可以得到n个c有n个线程的结果是肯定的。

这里有两件事对您不利。(1)除非您可以将线程分配给多个核心,否则您首先不能期望速度加快;使用单个核心,无论您是否并行化代码,该核心都有相同的工作量。(2)即使有多个核,并行性能对核上完成的计算与核之间必要的通信量之比也非常敏感在循环中,你会遇到很多这种“停下来等待另一个人”的性能问题。

这里有两件事对你不利除非您可以将线程分配给多个核心,否则首先就不能期望速度提高;使用单个核心,无论您是否并行化代码,该核心都有相同的工作量即使有多个核,并行性能对核上完成的计算与核之间必要的通信量之比也非常敏感在循环内部,你会遇到很多这种“停下来等待另一个人”的性能问题。

程序和算法的并行性通常是很难实现的,如果没有一些投资,也不会实现


我不认为直接使用线程是适合您的工具。试着深入研究一下,它更高层次。

程序和算法的并行性通常很难实现,没有一些投资也无法实现


我不认为直接使用线程是适合您的工具。试着研究一下,它更高级。

添加线程并不能神奇地让您的计算机更快…您还没有指定有多少内核,除非您至少有8个,否则8个计算绑定线程将使您的管理开销降低正在加载和切换线程…并且可能会导致更多缓存未命中,从而进一步降低速度。相关:。添加线程的可能重复不会神奇地提高计算机速度…您尚未指定有多少内核,除非您至少有8个计算绑定线程,否则8个计算绑定线程将降低您的速度,从而降低系统开销r管理和切换线程…并可能导致更多缓存未命中,从而进一步降低速度。相关:。学习OpenMP的可能副本是非常不自然的(我不会在严肃的生产环境中使用它,因为它很难抽象),但它1)很容易学习2)标准3)易于并行化大型循环。@Alexandre,你能解释一下“不自然”是什么意思吗?我总是发现OpenMP的语法比并行化for循环更难处理复杂的事情。它严重缺乏适当的OO抽象。@Alexandre,好吧,我明白你的意思了。但是在很多应用程序中,比如这里的
for
,循环是构建代码的工具。它认为编写此类问题的原始语言称为fortran:)是的,这种特定的应用程序可能会受益于一行OpenMP(因此我的投票)。学习OpenMP非常不自然(我不会在严肃的生产环境中使用它,因为它很难抽象)但是1)很容易学习2)标准3)很容易使用来并行化巨大的循环。@Alexandre,你能解释一下“不自然”是什么意思吗?我总是发现OpenMP的语法比并行化for循环更难处理复杂的事情。它严重缺乏适当的OO抽象。@Alexandre,好吧,我明白你的意思了。但是在很多应用程序中,比如这里的
for
,循环是构建代码的工具。它认为编写此类问题的原始语言叫做fortran:)是的,这个特定的应用程序可能会受益于一行OpenMP(因此我的upvote)。