线程合并排序给出无效结果

时间:2012-05-31 02:04:33

标签: c++ multithreading mergesort

我创建了一个合并排序,适用于非重复整数数组。 我正在尝试制作相同的多线程版本。

我收回了无效的结果。

void mergesort(int data[ ], size_t n)
{
    size_t n1; // Size of the first subarray
    size_t n2; // Size of the second subarray

    if (n > 1)
    {
        // Compute sizes of the subarrays.
        n1 = n / 2;
        n2 = n - n1;

        mergesort(data, n1);         // Sort from data[0] through data[n1-1]
        mergesort((data + n1), n2);  // Sort from data[n1] to the end

        // Merge the two sorted halves.
        merge(data, n1, n2);
    }
}

DWORD WINAPI threadedmergesort(LPVOID params)
{
    size_t n1; // Size of the first subarray
    size_t n2; // Size of the second subarray
    Params* parameters = (Params*) params;
    if (parameters->size > 1)
    {
        // Compute sizes of the subarrays.
        n1 = parameters->size / 2;
        n2 = parameters->size - n1;

        Params* p1 = new Params(parameters->dataArray, n1);
        //mergesort(data, n1);         // Sort from data[0] through data[n1-1]
        HANDLE h1 = CreateThread(NULL, 0, threadedmergesort, (LPVOID)p1, 0, NULL);
        Params* p2 = new Params(parameters->dataArray, n2);
        //mergesort((data + n1), n2);  // Sort from data[n1] to the end
        HANDLE h2 = CreateThread(NULL, 0, threadedmergesort, (LPVOID)p1, 0, NULL);
        WaitForSingleObject(h1, INFINITE);
        WaitForSingleObject(h2, INFINITE);

        // Merge the two sorted halves.
        merge(parameters->dataArray, n1, n2);
    }
    return (DWORD)0x0; //null
}

struct Params
{
    int* dataArray;
    int size;
    Params(int _dataArray[], int _size);
};
Params::Params(int _dataArray[], int _size)
{
    dataArray = _dataArray;
    size = _size;
}

有人可以评论为什么我会使用合并排序的线程版本获得无效结果以及我可以采取哪些措施来解决问题?

2 个答案:

答案 0 :(得分:1)

Params* p1 = new Params(parameters->dataArray, n1);
//mergesort(data, n1);         // Sort from data[0] through data[n1-1]
HANDLE h1 = CreateThread(NULL, 0, threadedmergesort, (LPVOID)p1, 0, NULL);
Params* p2 = new Params(parameters->dataArray, n2);
//mergesort((data + n1), n2);  // Sort from data[n1] to the end
HANDLE h2 = CreateThread(NULL, 0, threadedmergesort, (LPVOID)p1, 0, NULL);

看起来你正在向mergesorter发送两次p1。所以你只是排序列表的前半部分。改变你的第二个参数,一切都应该是正确的。

我的Mergesort看起来像这样:

DWORD WINAPI Mergesorter::mergesort_MT(LPVOID param)
{
    Mergesort_Params* i_mergesortParams = (Mergesort_Params*)param;
    unsigned int half = i_mergesortParams->numberOfValues / 2;
    DWORD threadId[2] = {0,0};
    HANDLE h[2];
    Mergesort_Params* mergesortParams;

    if(i_mergesortParams->numberOfValues > 1)
    {
        mergesortParams = new Mergesort_Params[2];
        mergesortParams[0].l_list = i_mergesortParams->l_list;
        mergesortParams[1].l_list = i_mergesortParams->l_list + half;
        mergesortParams[0].numberOfValues = half;
        mergesortParams[1].numberOfValues = i_mergesortParams->numberOfValues - half;

        h[0] = CreateThread(0,0,mergesort_MT,(void*)&mergesortParams[0],0,&threadId[0]);
        //WaitForSingleObject(h[0],INFINITE);
        h[1] = CreateThread(0,0,mergesort_MT,(void*)&mergesortParams[1],0,&threadId[1]);        
        //WaitForSingleObject(h[1],INFINITE);
        WaitForMultipleObjects(2,h,TRUE,INFINITE);
        merge_ST(i_mergesortParams->l_list,half,i_mergesortParams->numberOfValues - half);


    }

//delete threadId;
//delete h;
//delete mergesortParams;

return 0;
}

你解决了问题吗?现在我的问题是,我无法排序足够的值100000太多(单线程没有问题)我的CPU没有完全使用(25%在我的A8-3500M所以只有一个核心)

答案 1 :(得分:0)

要考虑几点:

  1. 请勿使用CreateThread,请改用beginThreadEx,有关详细信息,请参阅MSDN。
  2. 正如TOAOGG已经指出的那样,你有一个数据竞争,因为多个线程访问相同的内存,你没有同步。
  3. 您应该使用OS线程池而不是显式创建自己的线程。由于这是一种递归算法,因此您可能会面临更大数据集耗尽系统资源的风险。每个线程在用户空间中获得1MB的默认堆栈大小(不确定,但我认为内核空间中还有1MB),因此使用32位进程,您将很快触及该墙。另外,以快速创建新线程会产生巨大的开销,这将减少您在此处所需的任何并发增益。请参阅SubmitThreadPoolWork and related API
  4. 使用线程池API的另一种替代方法是使用OpenMP在C ++中执行并行for循环。 Visual Studio 2008及更高版本支持这些选项(当然还有英特尔编译器)。