如何将嵌套循环与pthreads并行化?

时间:2019-06-17 11:36:13

标签: c pthreads

我想通过使用pthreads并行化C中的嵌套循环(我有四个内核)。在循环内部,我只是向二维数组的每个索引分配一个值。

当我尝试将其与四个线程并行化时,它实际上使我的程序速度降低了3倍。我猜这是因为线程之间以某种方式相互阻塞。

这是要并行化的循环。

for ( i = 0; i < 1000; i++ ) 
      {
        for ( j = 0; j < 1000; j++ )
        {
          x[i][j] = 5.432;
        }
      }

我试图像这样并行化它。

void* assignFirstPart(void *val) {
     for ( i = 1; i < 500; i++ )
    {
      for ( j = 1; j < 500; j++ )
      {              

        w[i][j] = 5.432;

      }
    }
}

void* assignSecondPart(void *val) {
     for ( ia = 500; ia < 1000; ia++ )
    {
      for ( ja = 500; ja < 1000; ja++ )
      {             

        w[ia][ja] = 5.432;


      }
    }
}

void* assignThirdPart(void *val) {
     for ( ib = 1; ib < 1000; ib++ )
    {
      for ( jb = 500; jb < 1000; jb++ )
      {            

        w[ib][jb] = 5.432;


      }
    }
}

void* assignFourthPart(void *val) {

     for ( ic = 500; ic < 1000; ic++ )
    {
      for ( jc = 500; jc < 1000; jc++ )
      {              

        w[ic][jc] = 5.432;                 

      }
    }
}

success = pthread_create( &thread5, NULL, &assignFirstPart, NULL );
    if( success != 0 ) {
        printf("Couldn't create thread 1\n");
        return EXIT_FAILURE;
    }

success = pthread_create( &thread6, NULL, &assignSecondPart, NULL );
    if( success != 0 ) {
        printf("Couldn't create thread 2\n");
        return EXIT_FAILURE;
    }

    success = pthread_create( &thread7, NULL, &assignThirdPart, NULL );
    if( success != 0 ) {
        printf("Couldn't create thread 3\n");
        return EXIT_FAILURE;
    }

success = pthread_create( &thread8, NULL, &assignFourthPart, NULL );
    if( success != 0 ) {
        printf("Couldn't create thread 4\n");
        return EXIT_FAILURE;
    }

pthread_join( thread5, NULL );
pthread_join( thread6, NULL );
pthread_join( thread7, NULL );
pthread_join( thread8, NULL );

因此,正如我所说,将其并行化会大大降低程序的速度,因此我可能正在做完全错误的事情。感谢您的任何建议。

2 个答案:

答案 0 :(得分:1)

assignThirdPart与前两个回调的索引重叠。您的循环条件没什么意义,您应该将最外层循环的1000次迭代分成3个部分,例如:

for ( i = 0; i < 333; i++ ) // thread 1
...
for ( i = 333; i < 666; i++ ) // thread 2
..
for ( i = 666; i < 1000; i++ ) // thread 3
...

i = 1也不等同于i = 0

话虽如此,但这并不一定会提高性能。仅复制数据而不进行计算将使数据缓存在大多数计算机上成为瓶颈。如果将其拆分为3,则可能会干扰CPU的最佳缓存使用能力-这是高度特定于系统的。

在并行化过程中与内部迭代器配合使用时,您要做的是对要复制的整个区域进行分段-而不是使它线性化,而是在这里有一个线程副本,在那里又有一个线程副本,这增加了缓存的速度。完全。请阅读Why does the order of the loops affect performance when iterating over a 2D array?

然后当然还有线程创建开销,在进行基准测试时也应考虑在内。

即使所有操作都正确完成,使用3个线程也不一定更快。多线程并不是神奇的“始终具有最佳性能”的粉末,您可以将其撒在任意代码上以加快速度。高端线程CPU可以非常有效地处理1000个对齐的数据块。

答案 1 :(得分:0)

看起来您使用的是全局变量。

如果是这种情况,它们在与线程一起使用时会产生大量开销,并且会大大减慢速度。