双方向の分割統治を行おうとしていて、2 つの子を生成して、それらが終了するのを待っている場合は、おそらく次のようなものが必要です。
void *
routine (void * argument)
{
/* divide */
left_arg = f (argument);
right_arg = f (argument);
/* conquor */
pthread_create (left_child, NULL, routine, left_arg);
pthread_create (right_child, NULL, routine, right_arg);
/* wait for 'children' */
pthread_join (left_child, &left_return_val);
pthread_join (right_child, &right_return_val);
/* merge results & return */
}
わずかな改善は次のようになります。スリープする代わりに、「親スレッド」が適切な子のジョブを同期的に実行し、1 つ少ないスレッドを生成します。
void *
routine (void * argument)
{
/* divide */
left_arg = f (argument);
right_arg = f (argument);
/* conquor */
pthread_create (left_child, NULL, routine, left_arg);
/* do the right_child's work yourself */
right_return_val = routine (right_arg);
/* wait for 'left child' */
pthread_join (left_child, &left_return_val);
/* merge results & return */
}
ただし、N レベルの深さまで進むと、かなりの数の子ができます。P
得られるスピードアップは、CPU が実際の処理にkP
費やす時間と I/O などを待つ時間に大きく依存します。上記のようにスレッドを生成する代わりに、スレッドの「ワーカー プール」を設定し、kP
それらを再利用し続けることができます。このように、kP
スレッドが生成されると、それ以上生成されなくなります。
THREAD_POOL pool = new_thread_pool (k * P); /* I made this function up */
void *
routine (void * argument)
{
/* divide */
left_arg = f (argument);
right_arg = f (argument);
/* conquor */
left_thread = get_worker (pool); /* Blocks until a thread is free */
/* get left_thread to do processing for you */
right_thread = get_worker (pool); /* Blocks until a thread is free */
/* get right_thread to do processing for you */
/* wait for 'children' */
pthread_join (left_child, &left_return_val);
pthread_join (right_child, &right_return_val);
/* return the workers */
put_worker (pool, left_thread);
put_worker (pool, right_thread);
/* merge results & return */
}