我有两组已排序的元素,并希望将它们合并在一起,以便我以后可以并行化。我有一个简单的合并实现,它具有数据依赖性,因为它使用最大函数和可并行化合并的第一个版本,它使用二进制搜索来查找排名并计算给定值的索引。
getRank函数返回低于或等于给定针的元素数。
#define ATYPE int
int getRank(ATYPE needle, ATYPE *haystack, int size) {
int low = 0, mid;
int high = size - 1;
int cmp;
ATYPE midVal;
while (low <= high) {
mid = ((unsigned int) (low + high)) >> 1;
midVal = haystack[mid];
cmp = midVal - needle;
if (cmp < 0) {
low = mid + 1;
} else if (cmp > 0) {
high = mid - 1;
} else {
return mid; // key found
}
}
return low; // key not found
}
合并算法对两个有序集合a,b进行操作,并将结果存储到c。
void simpleMerge(ATYPE *a, int n, ATYPE *b, int m, ATYPE *c) {
int i, l = 0, r = 0;
for (i = 0; i < n + m; i++) {
if (l < n && (r == m || max(a[l], b[r]) == b[r])) {
c[i] = a[l];
l++;
} else {
c[i] = b[r];
r++;
}
}
}
void merge(ATYPE *a, int n, ATYPE *b, int m, ATYPE *c) {
int i;
for (i = 0; i < n; i++) {
c[i + getRank(a[i], b, m)] = a[i];
}
for (i = 0; i < m; i++) {
c[i + getRank(b[i], a, n)] = b[i];
}
}
当拥有大量元素并且仍然可以并行化时,合并操作非常慢,但simpleMerge总是更快,即使它无法并行化。
所以现在我的问题是,你知道更好的并行合并方法吗?如果有的话,你能指出我的方向还是我的代码不好?
答案 0 :(得分:0)
合并函数使用的算法最好通过渐近分析。复杂度为O(n + m)。您找不到更好的算法,因为I / O需要O(n + m)。
答案 1 :(得分:0)
simpleMerge
功能的复杂性:
O(n + m)
merge
功能的复杂性:
O(n*logm + m*logn)
如果不考虑这个问题,我建议并行化,就是找到一个围绕每个函数中间的值,使用类似于getRank函数的东西,并使用简单的合并。这可以是O(n + m + log m + log n) = O(n + m)
(即使你做了一些,但是在查找中间值的常量查找)。