单线程模式下的并行合并非常慢

时间:2013-01-12 15:26:53

标签: c algorithm merge parallel-processing

我有两组已排序的元素,并希望将它们合并在一起,以便我以后可以并行化。我有一个简单的合并实现,它具有数据依赖性,因为它使用最大函数和可并行化合并的第一个版本,它使用二进制搜索来查找排名并计算给定值的索引。

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总是更快,即使它无法并行化。

所以现在我的问题是,你知道更好的并行合并方法吗?如果有的话,你能指出我的方向还是我的代码不好?

2 个答案:

答案 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)(即使你做了一些,但是在查找中间值的常量查找)。