这是我在C++和D中比较并行性的一个实验。我使用相同的设计在两种语言中实现了一种算法(用于网络中社区检测的并行标签传播方案):并行迭代器获取句柄函数(通常为闭包)并将其应用于图中的每个节点。为什么D中的这个并行代码缩放非常糟糕?
下面是使用在d迭代器,实现从taskPool
std.parallelism
:
/**
* Iterate in parallel over all nodes of the graph and call handler (lambda closure).
*/
void parallelForNodes(F)(F handle) {
foreach (node v; taskPool.parallel(std.range.iota(z))) {
// call here
handle(v);
}
}
这是被传递手柄功能:
auto propagateLabels = (node v){
if (active[v] && (G.degree(v) > 0)) {
integer[label] labelCounts;
G.forNeighborsOf(v, (node w) {
label lw = labels[w];
labelCounts[lw] += 1; // add weight of edge {v, w}
});
// get dominant label
label dominant;
integer lcmax = 0;
foreach (label l, integer lc; labelCounts) {
if (lc > lcmax) {
dominant = l;
lcmax = lc;
}
}
if (labels[v] != dominant) { // UPDATE
labels[v] = dominant;
nUpdated += 1; // TODO: atomic update?
G.forNeighborsOf(v, (node u) {
active[u] = 1;
});
} else {
active[v] = 0;
}
}
};
的C++ 11执行几乎是相同但是使用OpenMP进行并行化。那么缩放实验显示了什么?
在这里,我检查弱缩放,加倍输入图形的尺寸,同时也增加一倍的线程的数目和测量的运行时间。理想将是一条直线,但当然有一些并行的开销。我在主函数中使用defaultPoolThreads(nThreads)
来设置D程序的线程数。 C++曲线看起来不错,但D曲线看起来非常糟糕。我做错了什么吗? D并行性,还是这反映严重的并行D程序的可扩展性?
p.s.编译器标记
为d:rdmd -release -O -inline -noboundscheck
为C++:-std=c++11 -fopenmp -O3 -DNDEBUG
PPS。东西一定是真的错了,因为d实现并行顺序比慢:
购买力平价。对于好奇,这里有水银克隆网址,这两种方案:
如果你没有使用openmp,那么性能会如何? – greatwolf
从检查它看起来不像dmd编译器目前支持openmp。如果一个版本使用openmp,而另一个版本不使用,它看起来不像是一个苹果对苹果的比较。 – greatwolf
@greatwolf除非我误解了你,否则我相信你错过了这一点。 D没有OpenMP,但它有'std.parallelism'库,它提供了类似的并行结构。实际上,D程序在运行时使用了许多内核。 – clstaudt