C++とDの並列性を比較した実験です。同じデザインを使用して、両方の言語でアルゴリズム(ネットワークでのコミュニティ検出のための並列ラベル伝播スキーム)を実装しました。並列反復子はハンドル関数クロージャ)、それをグラフのすべてのノードに適用します。ここDのこの並列コードはなぜひどくスケールされますか?
はDでイテレータで、std.parallelism
からtaskPool
を使用して実装:
/**
* 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);
}
}
これは渡されたハンドル関数である:C++ 11の実装がほぼ同一である
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;
}
}
};
並列化にはOpenMPを使用します。スケーリング実験は何を示していますか?ここ
Iはまた、スレッドの数を2倍にし、実行時間を測定しながら、入力グラフのサイズを倍増、弱いスケーリングを調べます。理想は直線ですが、もちろん並列処理のためのオーバーヘッドがあります。私はdefaultPoolThreads(nThreads)
を主な機能として使用して、Dプログラムのスレッド数を設定します。 C++のカーブはよく見えますが、Dのカーブは驚くほど悪く見えます。私は間違ったことをしていますか? D並列性、またはこれはパラレルDプログラムのスケーラビリティに悪影響を及ぼしますか?
p.s.コンパイラフラグD用
:C++用rdmd -release -O -inline -noboundscheck
:-std=c++11 -fopenmp -O3 -DNDEBUG
PPS。 Dの実装が順次より並列に遅いので何かが、本当に間違っている必要があります。
のPPP。好奇心のために、ここでは両方の実装のためのMercurialのクローンURLです:私は完全にあなたのアルゴリズムが動作するようになっているか理解していないので、
openmpなしで実行した場合のパフォーマンスはどうなりますか? – greatwolf
dmdコンパイラが現在openmpをサポートしているように見えることはありません。あるバージョンがopenmpを使用し、他のバージョンがそうでない場合、私にはリンゴとリンゴのコンパイルのようには見えません。 – greatwolf
@greatwolf私があなたを誤解しない限り、私はあなたがその点を見逃していると信じています。 DはOpenMPを持っていませんが、同様の並列構造を提供する 'std.parallelism'ライブラリを持っています。実際、Dプログラムは実行時に多くのコアを使用します。 – clstaudt