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、1 つの場所に割り当てて 4 つのスレッドで解放することです。arg_structスレッドごとに 1 つ割り当てる必要があります

于 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ます。

ただし、ジェームズが指摘したように、構造のスレッド/親で同期して、変更されていないことを確認する必要があります。これは、ミューテックスまたはその他のメカニズムを意味します。おそらく、for ループへの割り当ての移動は、最初は簡単です。

パート2:

私はWindowsで作業しています(したがって、現在実験することはできません)が、pthread_create param 3は、次のように定義されているスレッド関数matrixMultiplicationを参照していますvoid* matrixMultiplication( void* );-オンラインのマニュアルページから(署名に関して)正しいように見えます。void* fn (void* )

あなたの2番目のエラーについては、他の誰かに任せなければならないと思います。この投稿をコミュニティ 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 に答える