【发布时间】:2017-10-04 02:56:29
【问题描述】:
问题:我正在尝试通过以下方式实现合并排序,我有一个父级和两个子级。第一个孩子将自己使用归并排序,第二个孩子将通过以下方式实现:创建 2 个线程,第一个对数组的前半部分进行排序,第二个对其余部分进行排序。然后,在调用归并排序之后,他将再次为前半部分创建 2 个线程,为其余部分创建 2 个线程,依此类推,直到我们最终进入基本情况并完成。最后,我想检查第二个孩子实现归并排序的速度比第一个孩子快多少。
我的问题:我创建了 2 个孩子,第一个孩子正在实施排序合并,一切都很好。第二个孩子 - 我只能创建 2 个线程,而不是更多(然后每半个 2 个,依此类推),最后它既不打印数组也不打印完成日期。
这是第二个孩子的代码:
if((id2 = fork()) == 0 && id1 != 0)
{
printf("Child2: \n");
ans1 = pthread_create ( &thread1 , NULL , mergeSort ,(arr3, (arr_size / 2) - 1 ,arr_size - 1 )) ;
ans2 = pthread_create ( &thread2 , NULL , mergeSort ,(arr3, 0, (arr_size / 2)- 1 )) ;
ans3 = pthread_create ( &thread3 , NULL , printArray ,(arr3, arr_size) ) ;
execl("/bin/date", "date",0);
if ( ans1 != 0 || ans2 != 0 || ans3 != 0) {
printf ( " \n can't create threads " ) ;
exit(0) ;
}
pthread_join ( thread1 , NULL ) ;
pthread_join ( thread2 , NULL ) ;
pthread_join ( thread3 , NULL ) ;
}
我使用的是 UNIX,用于编译:
gcc -lpthread prog.c
用于执行:
./a.out
这是整个代码:
/* C program for Merge Sort */
#include<stdlib.h>
#include<stdio.h>
#include <pthread.h>
#define N 100
// Merges two subarrays of arr[].
// First subarray is arr[l..m]
// Second subarray is arr[m+1..r]
void merge(int arr[], int l, int m, int r)
{
int i, j, k;
int n1 = m - l + 1;
int n2 = r - m;
/* create temp arrays */
int L[n1], R[n2];
/* Copy data to temp arrays L[] and R[] */
for (i = 0; i < n1; i++)
L[i] = arr[l + i];
for (j = 0; j < n2; j++)
R[j] = arr[m + 1+ j];
/* Merge the temp arrays back into arr[l..r]*/
i = 0; // Initial index of first subarray
j = 0; // Initial index of second subarray
k = l; // Initial index of merged subarray
while (i < n1 && j < n2)
{
if (L[i] <= R[j])
{
arr[k] = L[i];
i++;
}
else
{
arr[k] = R[j];
j++;
}
k++;
}
/* Copy the remaining elements of L[], if there
are any */
while (i < n1)
{
arr[k] = L[i];
i++;
k++;
}
/* Copy the remaining elements of R[], if there
are any */
while (j < n2)
{
arr[k] = R[j];
j++;
k++;
}
}
/* l is for left index and r is right index of the
sub-array of arr to be sorted */
void mergeSort(int arr[], int l, int r)
{
if (l < r)
{
// Same as (l+r)/2, but avoids overflow for
// large l and h
int m = l+(r-l)/2;
// Sort first and second halves
mergeSort(arr, l, m);
mergeSort(arr, m+1, r);
merge(arr, l, m, r);
}
}
/* UTILITY FUNCTIONS */
/* Function to print an array */
void printArray(int A[], int size)
{
int i;
for (i=0; i < size; i++)
printf("%d ", A[i]);
printf("\n");
}
/* Driver program to test above functions */
int main()
{
int min = -1000, max = 1000;
int arr[10], arr2[10], arr3[10];
int i,r;
int arr_size = sizeof(arr)/sizeof(arr[0]);
int id1,id2;
//Threads init
pthread_t thread1 , thread2, thread3;
int ans1, ans2, ans3;
for( i = 0; i < arr_size; i++){
r = rand() % (max - min + 1);
arr[i] = r;
arr2[i] = r;
arr3[i] = r;
}
//printf("Before: \n");
if((id1 = fork()) == 0)
{
printf("Child1: \n");
mergeSort(arr2, 0, arr_size - 1);
printArray(arr2, arr_size);
execl("/bin/date", "date",0);
}
if((id2 = fork()) == 0 && id1 != 0)
{
printf("Child2: \n");
ans1 = pthread_create ( &thread1 , NULL , mergeSort ,(arr3, (arr_size / 2) - 1 ,arr_size - 1 )) ;
ans2 = pthread_create ( &thread2 , NULL , mergeSort ,(arr3, 0, (arr_size / 2)- 1 )) ;
ans3 = pthread_create ( &thread3 , NULL , printArray ,(arr3, arr_size) ) ;
execl("/bin/date", "date",0);
if ( ans1 != 0 || ans2 != 0 || ans3 != 0) {
printf ( " \n can't create threads " ) ;
exit(0) ;
}
pthread_join ( thread1 , NULL ) ;
pthread_join ( thread2 , NULL ) ;
pthread_join ( thread3 , NULL ) ;
}
wait();
if(id1 != 0 && id2 != 0){
printf("Given array is \n");
printArray(arr, arr_size);
printf("Father:\n");
mergeSort(arr, 0, arr_size - 1);
printArray(arr, arr_size);
execl("/bin/date", "date",0);
printf("\nSorted array is \n");
//printf("After: \n");
}
return 0;
}
编辑代码:
/* C program for Merge Sort */
#include<stdlib.h>
#include<stdio.h>
#include <pthread.h>
#include <time.h>
#define N 100
// Merges two subarrays of arr[].
// First subarray is arr[l..m]
// Second subarray is arr[m+1..r]
void merge(int arr[], int l, int m, int r)
{
int i, j, k;
int n1 = m - l + 1;
int n2 = r - m;
/* create temp arrays */
int L[n1], R[n2];
/* Copy data to temp arrays L[] and R[] */
for (i = 0; i < n1; i++)
L[i] = arr[l + i];
for (j = 0; j < n2; j++)
R[j] = arr[m + 1+ j];
/* Merge the temp arrays back into arr[l..r]*/
i = 0; // Initial index of first subarray
j = 0; // Initial index of second subarray
k = l; // Initial index of merged subarray
while (i < n1 && j < n2)
{
if (L[i] <= R[j])
{
arr[k] = L[i];
i++;
}
else
{
arr[k] = R[j];
j++;
}
k++;
}
/* Copy the remaining elements of L[], if there
are any */
while (i < n1)
{
arr[k] = L[i];
i++;
k++;
}
/* Copy the remaining elements of R[], if there
are any */
while (j < n2)
{
arr[k] = R[j];
j++;
k++;
}
}
/* l is for left index and r is right index of the
sub-array of arr to be sorted */
void mergeSort(int arr[], int l, int r)
{
if (l < r)
{
// Same as (l+r)/2, but avoids overflow for
// large l and h
int m = l+(r-l)/2;
// Sort first and second halves
mergeSort(arr, l, m);
mergeSort(arr, m+1, r);
merge(arr, l, m, r);
}
}
void* mergeSort2(void* args)
{
int* newArgs = (int*)args;
int l = newArgs[1];
int r = newArgs[2];
pthread_t thread1 , thread2;
int ans1, ans2;
if (l < r)
{
// Same as (l+r)/2, but avoids overflow for
// large l and h
int m = (r+l)/2;
int newArgs1[3] = {newArgs[0], l, m};
int newArgs2[3] = {newArgs[0], m+1, r};
ans1 = pthread_create ( &thread1 , NULL , mergeSort2 ,(void*)newArgs1);
ans1 = pthread_create ( &thread2 , NULL , mergeSort2 ,(void*)newArgs2);
pthread_join(thread1,NULL);
pthread_join(thread2,NULL);
merge(newArgs[0], l, m, r);
}
}
/* UTILITY FUNCTIONS */
/* Function to print an array */
void printArray(int A[], int size)
{
int i;
for (i=0; i < size; i++)
printf("%d ", A[i]);
printf("\n");
}
static void print_timestamp(void)
{
time_t now = time(0);
struct tm *utc = gmtime(&now);
char iso8601[32];
strftime(iso8601, sizeof(iso8601), "%Y-%m-%d %H:%M:%S", utc);
printf("%s\n", iso8601);
}
/* Driver program to test above functions */
int main()
{
int min = -1000, max = 1000;
int arr[10], arr2[10], arr3[10];
int i,r;
int arr_size = sizeof(arr)/sizeof(arr[0]);
int id1,id2;
int args[3] ={arr3, 0, arr_size - 1};
struct timeval tvalBefore, tvalAfter;
struct timeval tvalBefore1, tvalAfter1;
//Threads init
pthread_t thread1;
int ans1;
srand(time(NULL));
for( i = 0; i < arr_size; i++){
r = rand() % (max - min + 1);
arr[i] = r;
arr2[i] = r;
arr3[i] = r;
}
//printf("Before: \n");
if((id1 = fork()) == 0)
{
gettimeofday (&tvalBefore, NULL);
//Operation to do
printf("Child1: \n");
mergeSort(arr2, 0, arr_size - 1);
printArray(arr2, arr_size);
print_timestamp();
gettimeofday (&tvalAfter, NULL);
// Changed format to long int (%ld), changed time calculation
printf("Time in microseconds for sorting CHILD 1: %ld microseconds\n",
((tvalAfter.tv_sec - tvalBefore.tv_sec)*1000000L
+tvalAfter.tv_usec) - tvalBefore.tv_usec
); // Added semicolon
}
else if((id2 = fork()) == 0)
{
printf("Child2: \n");
//Start Timer
gettimeofday (&tvalBefore1, NULL);
//Operation to do
ans1 = pthread_create ( &thread1 , NULL , mergeSort2 ,(void*)args);
pthread_join ( thread1 , NULL ) ;
print_timestamp();
gettimeofday (&tvalAfter1, NULL);
// Changed format to long int (%ld), changed time calculation
printf("Time in microseconds for sorting CHILD 2: %ld microseconds\n",
((tvalAfter1.tv_sec - tvalBefore1.tv_sec)*1000000L
+tvalAfter1.tv_usec) - tvalBefore1.tv_usec
); // Added semicolon
}
else{
wait();
wait();
gettimeofday (&tvalBefore, NULL);
//Operation to do
printf("Given array is \n");
printArray(arr, arr_size);
printf("Father:\n");
mergeSort(arr, 0, arr_size - 1);
printArray(arr, arr_size);
print_timestamp();
gettimeofday (&tvalAfter, NULL);
// Changed format to long int (%ld), changed time calculation
printf("Time in microseconds for sorting Father: %ld microseconds\n",
((tvalAfter.tv_sec - tvalBefore.tv_sec)*1000000L
+tvalAfter.tv_usec) - tvalBefore.tv_usec
); // Added semicolon
}
return 0;
}
【问题讨论】:
-
是的,线程和进程传统上是不分性别的。无论如何,为什么在线程完成之前用
date替换整个子进程?execl调用应该替换整个过程为date,然后退出。 -
@EugeneSh。已编辑:)
-
@Useless 即使我将日期代码放在第三个 'pthread_join' 之后,它仍然不起作用。
-
您还(尝试)与 mergeSort 线程并行运行打印数组 - 在它们都完成之前它不应该运行(在这种情况下,您可以只
join他们和然后同步运行printArray) -
关于性能:不要期望线程解决方案更快...首先,创建新线程需要相当多的开销。要涵盖这一点,您需要大量数据才能看到任何好处。但是使用您的算法,您也需要大量线程,因此需要大量开销,此外,这些线程中的大多数无论如何都将处于非活动状态,因为不能同时活动的线程多于您拥有的 CPU 内核你的系统...
标签: c unix pthreads fork mergesort