这是D中的迭代器,使用stp.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); } }
这是传递的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; } } };
C11实现几乎相同,但使用OpenMP进行并行化.那么缩放实验显示什么呢?
在这里我检查弱缩放,使输入图形大小加倍,同时还使线程数量加倍并测量运行时间.理想将是一条直线,但是当然还有一些并行性的开销.我在main函数中使用defaultPoolThreads(nThreads)来设置D程序的线程数. C的曲线看起来不错,但D曲线看起来令人吃惊.我做错了w.r.t. D并行性,或者是否反映了并行D程序的可扩展性?
附:编译器标志
对于D:rdmd -release -O -inline -noboundscheck
对于C:-std = c 11 -fopenmp -O3 -DNDEBUG
PPS.某些事情一定是错误的,因为D的执行速度比顺序慢:
购买力平价.对于好奇,这两个实现都是Mercurial克隆URL:
> http://algohub.iti.kit.edu/parco/Prototypes/PLPd
> http://algohub.iti.kit.edu/parco/Prototypes/PLPcpp
解决方法
我把它添加到PLP.run的末尾:
writeln(nIterations);
有1个线程n = 19
有10个线程nIterations = 34
有100个线程nIterations = 90
所以你可以看到,它不是因为std.parallelism的一些问题需要更长时间,而只是因为它正在做更多的工作.
为什么你的代码不是线程安全的?
并行运行的函数是propagateLabels,它具有对标签的共享,非同步访问权限,nUpdated和active.谁知道这是什么奇怪的行为,但它不可能是好的.
在开始分析之前,您需要将算法修复为线程安全.