我正在对10多百万个带有RGB数据的uint64_t
从.RAW文件进行排序,而我的C程序中79%的时间都花费在qsort
上。我正在寻找针对这种特定数据类型的更快速的排序方法。
由于是原始图形数据,数字非常随机,并且大约80%是唯一的。不能期望部分排序或排好序的数据运行。 uint64_t
内的4个uint16_t
分别为R、G、B和零(可能是一个小计数<=〜20)。
我使用unsigned long long
编写了我能想到的最简单的比较函数(您不能只是将它们相减):
qsort(hpidx, num_pix, sizeof(uint64_t), comp_uint64);
...
int comp_uint64(const void *a, const void *b) {
if(*((uint64_t *)a) > *((uint64_t *)b)) return(+1);
if(*((uint64_t *)a) < *((uint64_t *)b)) return(-1);
return(0);
} // End Comp_uint64().
在StackExchange上有一个非常有趣的“编程谜题和代码高尔夫”,但是他们使用了float。然后有QSort、RecQuick、heap、stooge、tree、radix等。swenson/sort看起来很有趣,但没有(显而易见的)支持我的数据类型uint64_t。"快速排序"的时间最好。一些来源说系统qsort可以是任何东西,不一定是"快速排序"。C++ sort绕过了void指针的通用转换,在性能上比C实现了巨大的改进。必须有一种优化的方法将U8快速传递到64位处理器中。
系统/编译器信息:
我目前正在使用GCC和草莓珍珠岩。
gcc version 4.9.2 (x86_64-posix-sjlj, built by strawberryperl.com
Intel 2700K Sandy Bridge CPU, 32GB DDR3
windows 7/64 pro
gcc -D__USE_MINGW_ANSI_STDIO -O4 -ffast-math -m64 -Ofast -march=corei7-avx -mtune=corei7 -Ic:/bin/xxHash-master -Lc:/bin/xxHash-master c:/bin/stddev.c -o c:/bin/stddev.g6.exe
尝试改进的qsort
算法,QSORT()
!
尝试使用Michael Tokarev的内联qsort
算法。
“READY-TO-USE”?来自qsort.h
文档。
-----------------------------
* Several ready-to-use examples:
*
* Sorting array of integers:
* void int_qsort(int *arr, unsigned n) {
* #define int_lt(a,b) ((*a)<(*b))
* QSORT(int, arr, n, int_lt);
--------------------------------
Change from type "int" to "uint64_t"
compile error on TYPE???
c:/bin/bpbfct.c:586:8: error: expected expression before 'uint64_t'
QSORT(uint64_t, hpidx, num_pix, islt);
我找不到一个真正的、编译的、可工作的示例程序,只有关于“一般概念”的注释。
#define QSORT_TYPE uint64_t
#define islt(a,b) ((*a)<(*b))
uint64_t *QSORT_BASE;
int QSORT_NELT;
hpidx=(uint64_t *) calloc(num_pix+2, sizeof(uint64_t)); // Hash . PIDX
QSORT_BASE = hpidx;
QSORT_NELT = num_pix; // QSORT_LT is function QSORT_LT()
QSORT(uint64_t, hpidx, num_pix, islt);
//QSORT(uint64_t *, hpidx, num_pix, QSORT_LT); // QSORT_LT mal-defined?
//qsort(hpidx, num_pix, sizeof(uint64_t), comp_uint64); // << WORKS
这些“即用型”示例使用了int
、char *
和struct elt
类型。但是uint64_t
不是一种类型吗?尝试使用long long
。
QSORT(long long, hpidx, num_pix, islt);
c:/bin/bpbfct.c:586:8: error: expected expression before 'long'
QSORT(long long, hpidx, num_pix, islt);
下一步尝试: RADIX_SORT
:
结果: RADIX_SORT十分彻底!
I:\br3\pf.249465>grep "Event" bb12.log | grep -i Sort
<< 1.40 sec average
4) Time=1.411 sec = 49.61%, Event RADIX_SORT , hits=1
4) Time=1.396 sec = 49.13%, Event RADIX_SORT , hits=1
4) Time=1.392 sec = 49.15%, Event RADIX_SORT , hits=1
16) Time=1.414 sec = 49.12%, Event RADIX_SORT , hits=1
I:\br3\pf.249465>grep "Event" bb11.log | grep -i Sort
<< 5.525 sec average = 3.95 time slower
4) Time=5.538 sec = 86.34%, Event QSort , hits=1
4) Time=5.519 sec = 79.41%, Event QSort , hits=1
4) Time=5.519 sec = 79.02%, Event QSort , hits=1
4) Time=5.563 sec = 79.49%, Event QSort , hits=1
4) Time=5.684 sec = 79.83%, Event QSort , hits=1
4) Time=5.509 sec = 79.30%, Event QSort , hits=1
比起开箱即用的qsort
排序算法,这个算法快了3.94倍!
更重要的是,这里有实际可行的代码,而不仅仅是某位大师给你80%的内容,假设你知道他们所知道的一切,并且可以填补另外20%的空缺。
绝妙的解决方案!感谢Louis Ricci!
extern "C"
来使得你的其余代码仍然可以保持在C语言中。 - Adam