2

ハイパーキューブ通信の概念を理解するのに役立つ単純な並列マージソート アルゴリズムを作成しようとしています。ランダムな整数の配列を生成し、スレッドを割り当ててデータをソートする C プログラムがあります。各スレッドは、データのサブリストを順次ソートし、他のスレッドと比較交換操作を実行してサブリストをマージします。以下はスレッド関数です。

void *th_fun(void* args)
{
    int i, j;
    int my_id             = *((int*)args);

    int chunk_size        = N_DATA/N_THREADS;
    int start_index       = my_id*chunk_size;

    //set up the memory this thread will use
    th_mem[my_id].my_data = &data[start_index];
    th_mem[my_id].partner_data = malloc(sizeof(int)*chunk_size);
    for(i = 0; i < chunk_size; i++)
        th_mem[my_id].partner_data [i] = 0;

    //sort my data serially, should use a mergesort
    qsort((void*)th_mem[my_id].my_data, chunk_size, sizeof(int), compare);

    //wait for all threads to finish sorting
    barrier_simple();

    //compare-exchange accross hypercube
    int partner_id, op;
    int logth = log(N_THREADS)/log(2);
    for(i = 0; i < logth; i++)
    {
        partner_id = my_id ^ (int)pow(2,logth-i-1);

        //send my data to partner
        for(j = 0; j < chunk_size; j++)
        {
            th_mem[partner_id].partner_data[j] = th_mem[my_id].my_data[j];
        }

        //wait for all data to be sent
        barrier_simple();

        //get the lowest or highest elements between my_data, partner_data
        int x = my_id & (int)pow(2,logth-i-1);
        op = (x > 0 ? 1:-1);
        int* output = merge(th_mem[my_id].my_data, th_mem[my_id].partner_data, 
                            chunk_size, op);

        //save results
        for(j = 0; j < chunk_size; j++)
        {
            th_mem[my_id].my_data[j] = output[j];
        }
        free(output);

        //wait for all data to be merged
        barrier_simple();
    }

    free(th_mem[my_id].partner_data);
    pthread_exit(args);
}

4 つのスレッドでソートされた 12 のデータ要素を使用したサンプル実行 (出力はチャンク化され、どのスレッドがそのデータを担当しているかを示します):

./parallel_merge 12 4
Unsorted:
0:924 674 704 
1:495 554 645 
2:979 285 119 
3:878 80 620 

Serial sort: 
0:80 119 285 
1:495 554 620 
2:645 674 704 
3:878 924 979 

Parallel sort: 
0:80 119 285 
1:495 554 674 
2:620 645 704 
3:878 924 979 

ご覧のとおり、並列ソートは完全に正しいわけではありません (パフォーマンスの考慮事項を除けば、ofc)。多くの gdb を実行しましたが、ハイパーキューブ交換がうまくいかない理由を特定できません。どんな助けでも大歓迎です。私の参照は、ハイパーキューブテンプレートマージソートでした

4

0 に答える 0