マルチスレッドソートアプリケーション
実験要件
次のように機能するマルチスレッドソートプログラムを作成します。整数のリストは、同じサイズの2つの小さなリストに分割されます。2つの別々のスレッド(これをソートスレッドと呼びます)は、選択したソートアルゴリズムを使用して各サブリストをソートします。次に、2つのサブリストは、2つのサブリストを単一のソート済みリストにマージする3番目のスレッド(マージスレッド)によってマージされます。
グローバルデータはすべてのスレッドで共有されるため、データを設定する最も簡単な方法は、グローバル配列を作成することです。各ソートスレッドは、この配列の半分で機能します。ソートされていない整数配列と同じサイズの2番目のグローバル配列も確立されます。次に、マージスレッドは、2つのサブリストをこの2番目の配列にマージします。グラフィカルに、このプログラムは図4.20に従って構成されています。
このプログラミングプロジェクトでは、各並べ替えスレッドにパラメータを渡す必要があります。特に、各スレッドがソートを開始する開始インデックスを特定する必要があります。スレッドへのパラメーターの受け渡しの詳細については、プロジェクト1の手順を参照してください。
すべてのソートスレッドが終了すると、親スレッドはソートされた配列を出力します。
ソート
この実験では、各スレッドで配列を高速に並べ替える方法を選択します。
以下はクイックソートのコードモジュールです
void qsorts(int *start, int *end)
{
int nums = end - start;
if(nums > 0)
{
int index = 0;
int flag = start[0];
int i = 0, j = nums;
while(i != j)
{
while(j > i && start[j] >= flag)
--j;
start[index] = start[j];
index = j;
while(i < j && start[i] <= flag)
++i;
start[index] = start[i];
index = i;
}
start[index] = flag;
qsorts(start, start + (i - 1));
qsorts(start + j + 1, end);
}
}
void* work(void *arg) //线程排序函数
{
long index = (long)arg;
qsorts(num + index, num + index + thread_num - 1);
pthread_barrier_wait(&barrier);
pthread_exit(NULL);
}
ソートされた配列をマージする
スレッドにマージソートアルゴリズムを実装し、2つの配列を新しい配列にマージします
以下は、マージソートアルゴリズムのコードです
void merge(int *data, int start, int end, int *result)
{
int left_length = (end - start + 1) / 2 + 1;
int left_index = start;
int right_index = start + left_length;
int result_index = start;
while (left_index < start + left_length && right_index < end + 1) //store data into new array
{
if (data[left_index] <= data[right_index])
{
result[result_index++] = data[left_index++];
}
else
{
result[result_index++] = data[right_index++];
}
}
while (left_index < start + left_length)
{
result[result_index++] = data[left_index++];
}
while (right_index < end + 1)
{
result[result_index++] = data[right_index++];
}
}
void merge_sort(int *data, int start, int end, int *result)
{
if (1 == end - start) //last only two elements
{
if (data[start] > data[end])
{
int temp = data[start];
data[start] = data[end];
data[end] = temp;
}
return;
}
else if (end == start)
return; //last one element then there is no need to sort;
else {
//continue to divide the interval
merge_sort(data, start, (end - start + 1) / 2 + start, result);
merge_sort(data, (end - start + 1) / 2 + start + 1, end, result);
//start to merge sorted data
merge(data, start, end, result);
for (int i = start; i <= end; ++i)
{
data[i] = result[i];
}
}
}
完全なコード
以下は、この実験の完全なコードです。初期配列はプログラムで固定されています(上記の実験要件を満たすため)。もちろん、初期配列は手動で入力することもできます。
#include <pthread.h>
#include <stdio.h>
const int MAX = 19; //数组中最大数
const int n= 10
const int thread = 2; //the number of the aray
const int thread_num = 5; //the number of each thread
int num[10]={
7,12,19,3,18,4,2,6,15,8};
int result[10];
pthread_barrier_t barrier;
void qsorts(int *start, int *end)
{
int nums = end - start;
if(nums > 0)
{
int index = 0;
int flag = start[0];
int i = 0, j = nums;
while(i != j)
{
while(j > i && start[j] >= flag)
--j;
start[index] = start[j];
index = j;
while(i < j && start[i] <= flag)
++i;
start[index] = start[i];
index = i;
}
start[index] = flag;
qsorts(start, start + (i - 1));
qsorts(start + j + 1, end);
}
}
void* work(void *arg) //线程排序函数
{
long index = (long)arg;
qsorts(num + index, num + index + thread_num - 1);
pthread_barrier_wait(&barrier);
pthread_exit(NULL);
}
void merge(int *data, int start, int end, int *result)
{
int left_length = (end - start + 1) / 2 + 1;
int left_index = start;
int right_index = start + left_length;
int result_index = start;
while (left_index < start + left_length && right_index < end + 1) //store data into new array
{
if (data[left_index] <= data[right_index])
{
result[result_index++] = data[left_index++];
}
else
{
result[result_index++] = data[right_index++];
}
}
while (left_index < start + left_length)
{
result[result_index++] = data[left_index++];
}
while (right_index < end + 1)
{
result[result_index++] = data[right_index++];
}
}
void merge_sort(int *data, int start, int end, int *result)
{
if (1 == end - start) //last only two elements
{
if (data[start] > data[end])
{
int temp = data[start];
data[start] = data[end];
data[end] = temp;
}
return;
}
else if (end == start)
return; //last one element then there is no need to sort;
else {
//continue to divide the interval
merge_sort(data, start, (end - start + 1) / 2 + start, result);
merge_sort(data, (end - start + 1) / 2 + start + 1, end, result);
//start to merge sorted data
merge(data, start, end, result);
for (int i = start; i <= end; ++i)
{
data[i] = result[i];
}
}
}
int main()
{
int i;
pthread_t ptid;
gettimeofday(&start, NULL);
pthread_barrier_init(&barrier, NULL, thread + 1);
for (int i = 0; i < thread; ++i){
pthread_create(&ptid, NULL, work, (void *)(i * thread_num));
}
pthread_barrier_wait(&barrier);
merge_sort(num,0,9,result);
printf("The ordered array is :\n");
for (i = 0; i < n; ++i){
printf("%d\n", result[i]);
}
return 0;
}
実験結果
.cファイルをコンパイルします
ファイルスレッドを実行する
ヒント:本を验ダウンロード在Linux编译環状態下で
。PthreadライブラリはLinuxシステムの黙認ライブラリではありません。静的ライブラリlibpthread.aを使用する必要があります。次に、ファイルをコンパイルするときに「-lpthread」パラメータを追加します。さらに、ファイルに「thread」という名前を付けます。