C ++中的多线程矩阵乘法

时间:2012-10-29 07:56:24

标签: c++ multithreading posix

我一直遇到这个并行矩阵乘法代码的问题,在尝试访问我的结构中的数据成员时,我一直收到错误。

这是我的主要功能:

struct arg_struct
{
  int* arg1;
  int* arg2;
  int arg3;
  int* arg4;
};


int main()
{
  pthread_t allthreads[4];
  int A [N*N];
  int B [N*N];
  int C [N*N];
  randomMatrix(A);
  randomMatrix(B);
  printMatrix(A);
  printMatrix(B);
  struct arg_struct *args = (arg_struct*)malloc(sizeof(struct arg_struct));
  args.arg1 = A;
  args.arg2 = B;
  int x;
  for (int i = 0; i < 4; i++)
  {
     args.arg3 = i;
     args.arg4 = C;
     x = pthread_create(&allthreads[i], NULL, &matrixMultiplication, (void*)args); 
     if(x!=0)
     exit(1);
  }

  return 0;
}

和另一个C文件中使用的matrixMultiplication方法:

void *matrixMultiplication(void* arguments)
{
     struct arg_struct* args = (struct arg_struct*) arguments;
     int block = args.arg3;
     int* A = args.arg1;
     int* B = args.arg2;
     int* C = args->arg4;
     free(args);
     int startln = getStartLineFromBlock(block);
     int startcol = getStartColumnFromBlock(block);
     for (int i = startln; i < startln+(N/2); i++)
     {
        for (int j = startcol; j < startcol+(N/2); j++)
        {
          setMatrixValue(C,0,i,j);
          for(int k = 0; k < N; k++)
          {
             C[i*N+j] += (getMatrixValue(A,i,k) * getMatrixValue(B,k,j));
             usleep(1);
          } 
        }
     }
}

我得到的另一个错误是创建线程:“从'void()(int ,int *,int,int *)'无效转换为'void *() (void )'[-fpermissive] “

有谁能告诉我我做错了什么?

3 个答案:

答案 0 :(得分:4)

首先你非常糟糕地混合使用C和C ++,要么使用普通的C,要么使用C ++,在C ++中你只需使用newdelete

但是你错误的原因是你在一个地方分配arg_struct并在4个线程中释放它。您应该为每个线程分配一个arg_struct

答案 1 :(得分:1)

Big Boss是正确的,因为他已经确定了问题,但是要添加/补充他所做的回复。

选项1: 只需在循环中创建一个arg_struct并设置成员,然后将其传递给:

for(...)
{
    struct arg_struct *args = (arg_struct*)malloc(sizeof(struct arg_struct)); 
    args->arg1 = A;
    args->arg2 = B;    //set up args as now...
    ...
    x = pthread_create(&allthreads[i], NULL, &matrixMultiplication, (void*)args);
    ....
}

free调用保留在线程中,但现在您可以直接使用传递的结构,而不是在线程中创建本地。

选项2: 看起来你想要从结构内部将params复制到线程,所以你不需要动态分配。

只需创建一个arg_struct并设置成员,然后将其传递给:

arg_struct args;
//set up args as now...
for(...)
{
   ...
   x = pthread_create(&allthreads[i], NULL, &matrixMultiplication, (void*)&args);
}

然后移除free来电。

然而,正如James指出的那样,你需要在结构的线程/父级中进行同步,以确保它没有被更改。这意味着Mutex或其他一些机制。因此,可能更容易开始将分配移动到for循环。

第2部分:

我正在使用windows(所以我当前无法进行实验),但是pthread_create param 3指的是线程函数matrixMultiplication,它被定义为void* matrixMultiplication( void* ); - 它对我来说是正确的(签名方式)来自该手册在线,void* fn (void* )

我想我必须在第二次错误时推迟给别人。这篇文章是一个comunnity wiki条目,所以如果需要可以回答这个问题。

答案 2 :(得分:1)

我不清楚你要做什么。你开始一些线程, 然后你从main返回(退出流程),然后再获取任何内容 他们的结果。

在这种情况下,我可能直接使用任何动态分配。 (我会使用std::vector作为矩阵,它将使用动态 内部分配。)没有理由动态分配 arg_struct,因为它可以安全地复制。当然,你必须这样做 等到每个线程成功提取其数据之前 循环以构造下一个线程。这通常是使用 条件:新线程一旦有条件就会解除阻塞条件 从arg_struct中提取了论据(或者更好,你可以 使用boost::thread,为你做这部分)。或者,你 可以使用arg_struct的数组,但绝对没有理由 动态分配它们。 (如果由于某种原因你不能使用 对于std::vectorAB C,您想要分配这些 动态地,以避免任何堆栈溢出的风险。但 std::vector是一个更好的解决方案。)

最后,当然,您必须等待所有线程完成 在离开main之前。否则,线程将继续工作 不再存在的数据。在这种情况下,你应该 退出pthread_join之前的所有线程main。想必, 你也想对乘法的结果做些什么, 但无论如何,在所有线程完成之前退出main 访问矩阵将导致不确定的行为。