【问题标题】:Multithreaded merge sort programming多线程归并排序编程
【发布时间】: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 的某些变量(partp_i)。
  • @MegaMM - 我写的例子是特定于 Windows 的。唯一复杂的部分是创建 Windows 线程的开销,以及我用来防止线程在所有设置完成之前运行的信号量。为了避免线程之间共享变量的问题,我建议在启动任何线程之前拆分数组并设置相关变量。同样merge() 使用sorted[],它是从堆栈分配的,不适用于更大的数组。请改用newdelete
  • @MegaMM - 也正如我的示例代码所指出的,拥有比核心/超线程更多的线程会减慢进程。在具有超线程的 4 核处理器上从 4 线程到 8 线程几乎没有什么收获。你提到了多处理,但没有提到内存是如何共享的。对于多处理,每个进程都有一个单独的地址空间,如果这些进程不是都在单独的核心上运行,我想知道上下文切换开销。

标签: c++ multithreading sorting


【解决方案1】:

不明白为什么您的问题被否决了。据我了解,您已经开发了两个具有相同操作的程序。一种是用multi process 实现的,另一种是用multi thread 实现的。首先你需要知道multi processmulti thread之间的区别。我认为您在multi process 版本中使用了fork()。在multi process 版本中,操作系统为每个进程创建单独的data segment,因此当您使用fork() 时,操作系统为子进程分配一个新的内存空间并将所有内存从您的父进程复制到新创建的子进程的内存地点。但是在多线程的情况下永远不会发生。所以在多线程环境的内存访问过程中,如果使用同步内存访问,thread 版本的性能会受到严重影响,但multi process 版本不会。

【讨论】:

  • 我认为,-ve voter 应该解释他为什么投票给-ve。这将在未来改进我们的答案。如果我得到适当的解释,我将删除。谢谢
  • 我没有投反对票(实际上是来研究被投反对票的答案),但前 3 句话似乎是评论,而不是对我的回答。此外,由于对非代码使用code 格式,并且没有分成段落,因此这个答案不那么可读。您也错过了问题的重点,这不是关于进程与线程的问题,而是为什么程序会随着更多线程而变慢。
猜你喜欢
  • 2011-01-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-02-22
  • 1970-01-01
  • 2021-05-21
  • 2016-04-07
  • 1970-01-01
相关资源
最近更新 更多