4

スレッドを使用して、2 つの指定された配列間の行列乗算を実装する割り当て用のプログラムを作成しています。

コマンドライン引数として使用するスレッドの数を指定する必要があります。それらの数が最初の配列の行数よりも少ない場合は、ジョブ全体が完了するまで同じスレッドを再利用します。

私はそれを機能させることができましたが、配列の各行にのみスレッドを使用しています。たとえば、5x5 の乗算があり、使用するスレッドが 5 つ未満の場合、セグメンテーション違反が発生しますが、これは理にかなっています。

私の質問は次のとおりです:このスレッドがその仕事を終えた後、どうすればスレッドを再利用できますか? 前の例では、5x5 に 2 つのスレッドを使用する場合、プログラムは次のように動作する必要があることを意味します。

スレッド 1-> 行 1

スレッド 2->2 行目

スレッド 2->3 行目

スレッド 1-> 4 行目

4

1 に答える 1

3

いくつかの可能性がありますが、主な考え方は、スレッドを監視して、ジョブがいつ終了したかを検出し、まだやるべきことが残っているかどうかを知る方法を用意する必要があるということです。

頭に浮かぶ最初の方法は、実行中のすべてのスレッドを追跡する専用のスレッドを用意し、終了したらそれらをリサイクルすることです。ただし、そのためには、スレッドを同期させるメカニズムが必要です。これは、セマフォやミューテックス、またはメッセージを使用して実装できますが、その必要がない場合、その目的のためだけにコーディングするのは面倒です。 .

2 番目の方法は、自分でリサイクルするよう依頼することです。他の多くの言語には、継続と呼ばれるメカニズムがあり、まさにそれが可能ですが、C を扱っているため、手動で行う必要があります。幸いなことに、ここでは継続は実際には 1 つのタスクにすぎません。

したがって、継続を呼び出すメカニズムは実際には単なる関数であり、スレッドによって実行されるタスクを最初に実行し、次に次のいずれかを実行します。

  • タスクリストを確認します。このタスク リストには、セットアップ時に、タスクで実行する必要があるすべての作業を入力する必要があります。
  • 使用可能なスレッドのキューにスレッドを追加します。これは、他のスレッドによって再度チェックされ、新しいタスクが再割り当てされる必要があります。

明らかに、最初のオプションの方が簡単です。あなたの場合、セットアップ時に何をしなければならないかをすでに知っているので、セットアップ関数はタスクのリストを埋めてから、必要な数のスレッドを起動して、それらを許可することができますリサイクルは自分たちで。

以下は、最初に使用できる簡単なスケルトンです。

 typedef struct {
    /* task related data */
 } task_t;

 // basic list structure
 typedef struct {
   list_t *next;
   void *data; // here app specific data
 } list_t;

 list_t task_list; // your task list

 // a few operators to manipulate a list
 // implementation must use a mutex to avoid race conditions
 void list_push(list *l, void *data);
 void *list_pop(list *l);


 // thread function

 void do_task(task_t *task){
     while (task) {
       run_task(task); // that would be the matrix related function
       task = list_pop(&task_list);
 }

 // here a simple define for the number of threads
 // you might want to check the number of available cores instead

 #define MAX_THREAD_COUNT 4 

 int main() {

   pthread_t threads[MAX_THREAD_COUNT];

   setup_task_list();  // push all the work that must be done in the list
   int i;
   for (i = 0; i < MAX_THREAD_COUNT; i++) {
      pthread_create(threads + i, NULL, do_task, list_pop(&task_list));
   }

   // here wait for all the threads, or detach them

 }

これは、できることの基本的な概要であり、開始する必要があります。C リンク リストを扱う SO についていくつか質問があります。ここにあるものは同期する必要があり、ブロックしてはならず、NULL空になると戻ります。

于 2012-11-14T08:51:16.117 に答える