Вот один эксперимент, который я провел, сравнивая parallelism в С++ и D. Я реализовал алгоритм (параллельную схему распространения меток для обнаружения сообществ в сетях) на обоих языках, используя тот же дизайн: параллельный итератор получает функцию дескриптора (обычно замыкание) и применяет его для каждого node на графике.
Вот итератор в D, реализованный с помощью taskPool
from 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);
}
}
И это передаваемая функция handle:
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;
}
}
};
Реализация С++ 11 почти идентична, но использует OpenMP для распараллеливания. Итак, что показывают масштабные эксперименты?
Здесь я рассматриваю слабое масштабирование, удваивая размер входного графа, а также удваивая количество потоков и измеряя время работы. Идеал был бы прямой линией, но, конечно, для parallelism есть некоторые накладные расходы. Я использую defaultPoolThreads(nThreads)
в своей основной функции для установки количества потоков для программы D. Кривая для С++ выглядит неплохо, но кривая для D выглядит удивительно плохо. Я что-то делаю неправильно w.r.t. D parallelism, или это плохо отражается на масштабируемости параллельных программ D?
p.s. флаги компилятора
для D: rdmd -release -O -inline -noboundscheck
для С++: -std=c++11 -fopenmp -O3 -DNDEBUG
ПФС. Что-то должно быть действительно неправильно, потому что реализация D медленнее параллельно, чем последовательно:
ЧГП. Для любопытных, вот URL-адреса Mercurial для обеих реализаций: