【发布时间】:2018-02-20 15:44:01
【问题描述】:
This is the experiment result - runtime of original verison, multiprocess version, and multithread version我正在比较使用多进程和多线程的归并排序编程的性能。比较在线程/进程的数量、数组中的元素数量方面有所下降。令我沮丧的是反直觉的结果:随着线程/进程数量的增加,运行时间增加;多进程版本几乎比另一个快 10 倍。正如我所料,多线程版本应该会赢。我附上多线程源代码。请帮我看看发生了什么。谢谢大家!
#include <iostream>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>
// number of elements in array
// number of threads
int MAX;
int THREAD_MAX;
// array bellow is to store the right edge of a divided array
int index[20] = {0};
int p_i = 0;
using namespace std;
int *a;
int part = 0;
// merge function for merging two parts
void merge(int l1, int h1, int h2) {
int count = h2 - l1 + 1;
int sorted[count];
int i = l1, k = h1 + 1, m = 0;
while (i <= h1 && k <= h2) {
if (a[i]<a[k])
sorted[m++] = a[i++];
else if (a[k]<a[i])
sorted[m++] = a[k++];
else if (a[i] == a[k]) {
sorted[m++] = a[i++];
sorted[m++] = a[k++];
}
}
while (i <= h1)
sorted[m++] = a[i++];
while (k <= h2)
sorted[m++] = a[k++];
int arr_count = l1;
for (i = 0; i<count; i++, l1++)
a[l1] = sorted[i];
}
// merge sort function
void merge_sort(int low, int high) {
// calculating mid point of array
int mid = low + (high - low) / 2;
if (low < high) {
// calling first half
merge_sort(low, mid);
// calling second half
merge_sort(mid + 1, high);
// merging the two halves
merge(low, mid, high);
}
}
// thread function for multi-threading
void* merge_sort(void* arg) {
int thread_part = part++;
// calculating low and high
int low = thread_part * (MAX / THREAD_MAX);
int high = (thread_part + 1) * (MAX / THREAD_MAX) - 1;
// allocate the rest part of original array to the last thread
if(thread_part == THREAD_MAX -1){
high = MAX - 1;
}
// store the right edge of each divided array
index[++p_i] = high;
// evaluating mid point
int mid = low + (high - low) / 2;
merge_sort(low, mid);
merge_sort(mid + 1, high);
merge(low, mid, high);
}
void isSorted(int len) {
if (len == 1) {
printf("Sorting Done Successfully\n");
return;
}
int i;
for (i = 1; i<len; i++) {
if (a[i]<a[i - 1]) {
printf("Sorting Not Done\n");
return;
}
}
printf("Sorting Done Successfully\n");
return;
}
// Driver Code
int main() {
cout << "Enter No of elements of Array:";
cin >> MAX;
cout << "Enter No of Thread:";
cin >> THREAD_MAX;
// generating random values in array
a = new int[MAX];
srand(time(NULL));
for (int i = 0; i < MAX; i++) {
a[i] = rand();
}
// t1 and t2 for calculating time for merge sort
clock_t t1 = clock();
pthread_t threads[THREAD_MAX];
// creating threads
for (int i = 0; i < THREAD_MAX; i++) {
pthread_create(&threads[i], NULL, merge_sort, (void*)NULL);
}
// joining all threads
for (int i = 0; i < THREAD_MAX; i++) {
pthread_join(threads[i], NULL);
}
// merging the final parts
int p = 1;
int mid, high;
for(int q = 1; q < THREAD_MAX; q++) {
mid = index[p];
p++;
high = index[p];
merge(0, mid, high);
}
clock_t t2 = clock();
cout << "Time taken: " << (double)(t2 - t1)/ CLOCKS_PER_SEC << endl;
isSorted(MAX);
// displaying sorted array
/*cout << "Sorted array: ";
for (int i = 0; i < MAX; i++)
cout << a[i] << " ";*/
return 0;
}
【问题讨论】:
-
你的问题是什么?
-
int sorted[count];不是有效的 C++,它使用 VLA 扩展。 -
您有并发访问,但没有同步导致 UB 的某些变量(
part、p_i)。 -
@MegaMM - 我写的例子是特定于 Windows 的。唯一复杂的部分是创建 Windows 线程的开销,以及我用来防止线程在所有设置完成之前运行的信号量。为了避免线程之间共享变量的问题,我建议在启动任何线程之前拆分数组并设置相关变量。同样
merge()使用sorted[],它是从堆栈分配的,不适用于更大的数组。请改用new和delete。 -
@MegaMM - 也正如我的示例代码所指出的,拥有比核心/超线程更多的线程会减慢进程。在具有超线程的 4 核处理器上从 4 线程到 8 线程几乎没有什么收获。你提到了多处理,但没有提到内存是如何共享的。对于多处理,每个进程都有一个单独的地址空间,如果这些进程不是都在单独的核心上运行,我想知道上下文切换开销。
标签: c++ multithreading sorting