【发布时间】:2013-12-07 11:51:49
【问题描述】:
昨天我用一个大数据集(2000万个节点)测试了我的景观进化程序,运行速度毫无疑问是不能接受的。在调试过程中,我注意到某个功能会减慢整个系统的速度。所以我想给它添加多线程进程。
然而,函数本身是一个带有指针迭代器的嵌套循环,我相信在这个过程中必须锁定一些数据。
基本上我想做的是计算每个节点的贡献区域。贡献区域,顾名思义,是上游节点所有区域的乘积(总和)。
这是两个函数的代码,
for( curnode = nodIter.FirstP(); nodIter.IsActive();
curnode = nodIter.NextP() ) //iterating thru a linked-list of pointers to active stream nodes (*IsActive* returns a bool value)
{
CalcDRArea( curnode, curnode->getVArea() ); //calls another function and pass a pointer to current node as well as a value of its VArea
}
void CalcDRArea( NodeClass *curnode, double addedArea )
{
// As long as the current node is neither a boundary nor non-valid, add
// _addedArea_ to its total drainage area and advance to the next node downstream
while( (curnode->ReachBoundary() == NonBoundary) &&
(curnode->valid()!=Nonvalid) )
{
curnode->AddDrArea( addedArea ); //*AddDrArea* is a simple inline function *`"drarea +=value"`*
curnode = curnode->getDownStreammNeighbor(); // *getDownstrmNbr()* reruns a pointer to the downstream node
}
}
这里是节点及其流动方向的简单说明
A B C D
\ | / |
E F G H
| |
I Q K L
| /
M N O P
//letters are stream nodes and slashes are their flowing directions
我的计划是在第一个函数 for 循环的开头使用 OpenMP 实现多线程。理想情况下,它将创建多个线程来分别计算每个节点。
但是,如上图所示,后续进程可以处理类似的流
A-> F -> Q -> N
B-> F -> Q -> N
C-> F -> Q -> N
很容易,但它肯定会在多线程条件下引起问题。
根据我刚刚从 OpenMP 的文档中读到的内容,flush 和 lock 可能是执行此操作的正确方法,但我现在和那里仍然一无所知可能仍然是此循环中的其他潜在问题(例如 OpenMP 的 gcc 版本不支持“!=”)。
====更新====== 面积有两种:vArea,即每个节点的面积; drArea 是当前节点的面积与其所有上游节点的面积之和。 我想知道是否可以将当前功能更改为:
for( active node iterator)
{
if(currentNode.hasDownStreamNode)
{
downStreamNode.drArea += currentNode.vArea + currentNode.DrArea;
}
CurrentNode.drArea += currentNode.varea;
}
【问题讨论】:
-
这似乎很容易适用于动态编程——在尝试多线程之前使用更好的算法通常不是一个坏主意。您基本上是在 O(n^2) 而不是 O(n) 中执行此操作。
-
你能给我一些关于更好算法的建议吗?我确实意识到这是一个 O(n*n) 并且不知道如何使它更简单。谢谢。
-
这取决于您的算法究竟是如何工作的,因为从给定的代码中并不清楚,但基本思想是
F的值为A+B+C+F,而Q 的值为@987654328 @ 等等。因此,要计算一个节点的值,您只需查看其所有前任 一次 的已计算值,而不是从每个起始节点遍历所有节点。
标签: c++ multithreading openmp nested-loops