c语言中的并行快速排序

c语言中的并行快速排序,c,parallel-processing,openmp,quicksort,C,Parallel Processing,Openmp,Quicksort,在对c语言中并行快速排序的实现进行了大量的搜索之后,我准备亲自编写它。(我需要对大约100万个文本字符串的数组进行排序。)我发现的所有实现似乎都在qsort函数本身内部分配了工作,这会在划分每个线程相对较少的工作时产生大量开销 将100万个字符串除以线程数(在我的例子中是24个线程),然后让它们各自处理一个部分,然后进行合并排序,这样会不会快得多?诚然,这在理论上有一个缺点,即它不是就地排序,但在内存不足的情况下,这不是一个问题。它运行的机器有12个(非常快的)物理/24个逻辑核和192 GB(

在对c语言中并行快速排序的实现进行了大量的搜索之后,我准备亲自编写它。(我需要对大约100万个文本字符串的数组进行排序。)我发现的所有实现似乎都在qsort函数本身内部分配了工作,这会在划分每个线程相对较少的工作时产生大量开销


将100万个字符串除以线程数(在我的例子中是24个线程),然后让它们各自处理一个部分,然后进行合并排序,这样会不会快得多?诚然,这在理论上有一个缺点,即它不是就地排序,但在内存不足的情况下,这不是一个问题。它运行的机器有12个(非常快的)物理/24个逻辑核和192 GB(是的,千兆字节)内存。目前,即使在这台机器上,排序也需要将近8分钟

快速排序涉及对列表的初始传递,它将列表排序为高于和低于轴心的部分

为什么不在一个线程中执行此操作,然后生成另一个线程并将其委托给另一半线程,而现有线程则接管另一半线程,依此类推

分开不是更快吗 100万个字符串由 线程(在我的例子中是24个线程),以及 让他们每个人在一个部分上工作,并且 那就做一个排序

这是个好主意

但是您可以通过为
quick sort
merge sort
编写玩具程序,并利用它们的算法/运行时行为来进行观察

比如说<代码>快速排序在
分割时进行排序
过程(
pivot
元素将在该迭代结束时放在其最终位置)和
合并排序
合并时进行排序
(整个工作集分解(分割)后进行排序)进入非常精细的单元,可以直接与其他精细单元进行比较(
=
strcmp()

根据工作集的性质混合算法是一个好主意

关于并行排序,这里是我的
并行合并排序
,供您开始使用

#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>

#define NOTHREADS 2

/*

gcc -ggdb -lpthread parallel-mergesort.c 


NOTE: 
The mergesort boils downs to this.. 
Given two sorted array's how do we merge this?

We need a new array to hold the result of merging
otherwise it is not possible to do it using array, 
so we may need a linked list

*/

int a[] = {10, 8, 5, 2, 3, 6, 7, 1, 4, 9};

typedef struct node {
int i;
int j;
} NODE;

void merge(int i, int j)
{
        int mid = (i+j)/2;
        int ai = i;
        int bi = mid+1;

        int newa[j-i+1], newai = 0;

        while(ai <= mid && bi <= j) {
                if (a[ai] > a[bi])
                        newa[newai++] = a[bi++];
                else                    
                        newa[newai++] = a[ai++];
        }

        while(ai <= mid) {
                newa[newai++] = a[ai++];
        }

        while(bi <= j) {
                newa[newai++] = a[bi++];
        }

        for (ai = 0; ai < (j-i+1) ; ai++)
                a[i+ai] = newa[ai];

}

void * mergesort(void *a)
{
                NODE *p = (NODE *)a;
                NODE n1, n2;
                int mid = (p->i+p->j)/2;
                pthread_t tid1, tid2;
                int ret;

                n1.i = p->i;
                n1.j = mid;

                n2.i = mid+1;
                n2.j = p->j;

                if (p->i >= p->j) return;

                ret = pthread_create(&tid1, NULL, mergesort, &n1);
                if (ret) {
                        printf("%d %s - unable to create thread - ret - %d\n", __LINE__, __FUNCTION__, ret);    
                        exit(1);
                }


                ret = pthread_create(&tid2, NULL, mergesort, &n2);
                if (ret) {
                        printf("%d %s - unable to create thread - ret - %d\n", __LINE__, __FUNCTION__, ret);    
                        exit(1);
                }

                pthread_join(tid1, NULL);
                pthread_join(tid2, NULL);

                merge(p->i, p->j);
                pthread_exit(NULL);
}


int main()
{
                int i;
                NODE m;
                m.i = 0;
                m.j = 9;
                pthread_t tid;

                int ret; 

                ret=pthread_create(&tid, NULL, mergesort, &m);
                if (ret) {
                        printf("%d %s - unable to create thread - ret - %d\n", __LINE__, __FUNCTION__, ret);    
                        exit(1);
                }

                pthread_join(tid, NULL);

                for (i = 0; i < 10; i++)
                                printf ("%d ", a[i]);

                printf ("\n");

                // pthread_exit(NULL);
                return 0;
}
#包括
#包括
#包括
#定义第2条
/*
gcc-ggdb-lpthread并行mergesort.c
注:
合并排序归结起来就是这样。。
给定两个排序数组,如何合并?
我们需要一个新数组来保存合并的结果
否则,无法使用数组执行此操作,
所以我们可能需要一个链表
*/
INTA[]={10,8,5,2,3,6,7,1,4,9};
类型定义结构节点{
int i;
int j;
}节点;
无效合并(int i,int j)
{
int mid=(i+j)/2;
int ai=i;
int-bi=mid+1;
int-newa[j-i+1],newai=0;
而(ai i,;
n1.j=mid;
n2.i=mid+1;
n2.j=p->j;
如果(p->i>=p->j)返回;
ret=pthread_create(&tid1,NULL,mergesort,&n1);
如果(ret){
printf(“%d%s-无法创建线程-ret-%d\n”,\uuuuu行\uuuuuuuu,函数\uuuuuuuu,ret);
出口(1);
}
ret=pthread_create(&tid2,NULL,mergesort,&n2);
如果(ret){
printf(“%d%s-无法创建线程-ret-%d\n”,\uuuuu行\uuuuuuuu,函数\uuuuuuuu,ret);
出口(1);
}
pthread_join(tid1,NULL);
pthread_join(tid2,NULL);
合并(p->i,p->j);
pthread_exit(NULL);
}
int main()
{
int i;
节点m;
m、 i=0;
m、 j=9;
pthread_t tid;
int ret;
ret=pthread_create(&tid,NULL,mergesort,&m);
如果(ret){
printf(“%d%s-无法创建线程-ret-%d\n”,\uuuuu行\uuuuuuuu,函数\uuuuuuuu,ret);
出口(1);
}
pthread_join(tid,NULL);
对于(i=0;i<10;i++)
printf(“%d”,a[i]);
printf(“\n”);
//pthread_exit(NULL);
返回0;
}

祝您好运!

您是否考虑过使用专门设计的排序算法对字符串进行排序? 这似乎比尝试实现自定义快速排序更好。算法的具体选择可能取决于字符串的长度以及它们之间的差异,但a可能不是一个坏主意

一个关于字符串排序的快速出现。我还没有读过它,但Sedgewick和Bentley真的知道他们的东西。根据摘要,他们的算法是快速排序和基数排序的混合体

另一种可能的解决方案是从C++中封装并行排序算法。GNU的STL实现有一个,它包含并行快速排序实现。


这可能是最简单的解决方案。

要使多线程快速排序可行,需要优化内存访问,以使大多数排序工作在非共享缓存(L1和L2)内执行。我打赌单线程快速排序将比多线程快,除非您准备投入大量工作

一种测试方法可以是一个线程对上半部分进行排序,另一个线程对下半部分进行排序

对于一个特殊的适应字符串的排序例程,这个概念听起来很奇怪。我的意思是,对只包含字符串(或整数)的向量进行排序的情况并不多特别有用。通常,数据将以列和行的形式组织在一个表中,您将希望按包含字母的一列对行进行排序,如果它们相等,您将使用包含时间戳或排名或其他内容的附加列进行排序。因此,排序例程应该能够处理多级排序规则可以指定任何类型的数据(布尔值、整数、日期、,