Yesterday I tested my program of landscape evolution with a big data set(20 Million nodes), without a doubt the running speed was unacceptable. During debugging I noticed that it was a certain function which slowed the whole system down. So I'd like to add multithreading process to it.
However, the function itself is a nested loop with pointer iterators and I believe some of the data has to be locked during the process.
Basically what I was trying to do is to calculate the contributing area of each node. Contributing area, as suggested by its name, is a product (sum) of of all area from upstream node.
Here is the code of that two functions,
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
}
}
Here is a simple illustration of nodes and their flowing direction
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
My plan is to use OpenMP to implement multithreading at the beginning of first function, the for loop. Ideally it will create several threads to calculate each node separately.
However, as shown in figure above, a sequent process can handle streams like
A-> F -> Q -> N
B-> F -> Q -> N
C-> F -> Q -> N
easily, but it will definitely cause problem in a multithreading conditions.
From what I've just read from OpenMP's document, flush and lock might be the right way to do this, but still I am quite clueless right now and there might still be other potential issues within this loops (like gcc ver. of OpenMP doesn't support "!=").
====Update ====== There are two kinds of areas: vArea, which is the area of each node; and drArea which is the sum of the area of current node and area from all its upstream nodes. I was wondering if I can change the current function to this :
for( active node iterator)
{
if(currentNode.hasDownStreamNode)
{
downStreamNode.drArea += currentNode.vArea + currentNode.DrArea;
}
CurrentNode.drArea += currentNode.varea;
}
Fhas the value ofA+B+C+F, while Q has the valueA+B+C+F+Qand so on. So to compute the value of one node you only have to look at the already computed values of all its predecessors once instead of iterating through all nodes from each starting node.