使用 OpenMP 并行化 C 中的基数排序
Posted
技术标签:
【中文标题】使用 OpenMP 并行化 C 中的基数排序【英文标题】:Parallelization of radix-sort in C with OpenMP 【发布时间】:2015-03-04 20:50:36 【问题描述】:您将如何将 C 中的基数排序算法与 OpenMP 并行化?
我的程序是对典型基数排序的修改:它根据数字的二进制表示对整数数组进行排序,您可以在其中改变应解释为一位数的位数(即本质上将用于根据整数的大小来获得不同的运行时间)。
我有一个接受三个参数的基函数:
// n is the number of elements in data
// b is number of bits that should be interpreted as one digit
void radix(int* data, int n, int b);
此外,我的基数函数以b
为增量遍历所有位(int:32 位):
for(bit = 0; bit < 32; bit += b) ...
其中包含三个部分:
计算某个数字(实际上是位)的出现次数,以确定存储桶需要多少存储空间。bucket[(data[i] >> bit) & (int)(pow(2,b)-1)]++
将值放入临时数组(桶)中。
bitval = (data[i] >> bit) & (int)(pow(2,b)-1)
temp_data[bucket[bitval]++] = data[i]
将临时存储桶中的值复制到给函数的*data
指针。
for(i = 0; i < n; i++) data[i] = temp_data[i]
【问题讨论】:
【参考方案1】:并行化将成为一个问题,因为限制因素是内存带宽(CPU 开销非常小,并且只有一条内存总线)。
同样不使用浮点函数 pow(2,b),而是根据 b 创建位掩码和右移计数:
numberOfBits = b;
shiftCount = 0;
while(1) // main loop
// set numberOfBuckets
numberOfBuckets = 1 << numberOfBits;
bitMask = numberOfBuckets - 1;
// code to generate histogram for this field goes here
// ...
shiftCount += numberOfBits;
// check for partial bit field
if((shiftCount + numberOfBits) > (8*sizeof(unsigned int)))
numberOfBits = (8*sizeof(unsigned int)) - shiftCount;
shiftCount = (8*sizeof(unsigned int)) - numberOfBits;
continue; // do partial bit field
// check for done
if(shiftCount == (8*sizeof(unsigned int)))
break; // done
如果对有符号整数进行排序,则需要针对最重要的字段进行调整(符号整数的算术右移也取决于编译器/平台)。一种解决方案(对于有符号整数的二进制补码)是强制转换为无符号整数并对符号位进行补码以生成桶索引。
【讨论】:
我从 pow(2,b) 更改为 1 bitOffset 是如何工作的,您愿意详细说明它的用法吗? @LarsErikStorbukås - 我修正了我的答案,直接使用班次计数。 (前面的代码有错误,应该是( shiftCount = (8*sizeof(unsigned int) - bitOffset - numberofBits; )。 @LarsErikStorbukås - 仅当元素中的位数不是字段中位数的精确倍数时才需要检查部分位字段,例如,32 位无符号位域大小为 7 的整数,最高有效域只有 4 位(从 MSF 到 LSF 的位域大小为 4 7 7 7 7)。以上是关于使用 OpenMP 并行化 C 中的基数排序的主要内容,如果未能解决你的问题,请参考以下文章