0

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

这是我的主要功能:

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] 的无效转换”

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

4

3 回答 3

4

首先,您将 C 和 C++ 混合得非常糟糕,要么使用普通 C,要么使用 C++,在 C++ 中,您可以简单地使用newand delete

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

于 2012-10-29T08:01:39.170 回答
1

大老板在他发现问题的意义上是正确的,但要添加/增强他所做的答复。

选项 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: 看起来您无论如何都想将结构内部的参数复制到线程,因此您不需要动态分配。

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

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

然后删除free呼叫。

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

第2部分:

我正在 Windows 上工作(所以我目前无法进行实验),但 pthread_create 参数 3 指的是线程函数 matrixMultiplication ,它被定义为void* matrixMultiplication( void* );- 从联机手册页中我看起来是正确的(签名明智),void* fn (void* )

我想我将不得不在你的第二个错误上听从别人的意见。将此帖子设为社区 wiki 条目,因此如果需要,可以将答案放入其中。

于 2012-10-29T08:16:54.023 回答
1

我不清楚你想做什么。您启动一些线程,然后main在从它们获得任何结果之前从(退出进程)返回。

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

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

于 2012-10-29T10:25:16.123 回答