Skip to content
This repository was archived by the owner on Mar 20, 2023. It is now read-only.

Commit c868909

Browse files
iomaganarisChristos Kotsalos
andauthored
Hines Matrix solver and cell permute docs (#726)
* Initial comments added for the cell permutation algorithms * Additional comments on permutation strategies Co-authored-by: Christos Kotsalos <christos.kotsalos@epfl.ch>
1 parent 7b0b6d9 commit c868909

File tree

4 files changed

+60
-11
lines changed

4 files changed

+60
-11
lines changed

coreneuron/network/tnode.hpp

Lines changed: 30 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -17,20 +17,42 @@ class TNode;
1717

1818
using VecTNode = std::vector<TNode*>;
1919

20+
/**
21+
* \class TNode
22+
* \brief TNode is the tree node that represents the tree of the compartments
23+
*/
2024
class TNode {
2125
public:
2226
TNode(int ix);
2327
virtual ~TNode();
2428
TNode* parent;
2529
VecTNode children;
26-
size_t mkhash();
27-
size_t hash;
28-
size_t treesize;
29-
size_t nodevec_index;
30-
size_t treenode_order;
31-
size_t level;
32-
size_t cellindex;
33-
size_t groupindex;
30+
size_t mkhash(); /// Hash algorith that generates a hash based on the hash of the children and
31+
/// the number of compartments of the children
32+
size_t hash; /// Hash value generated by mkhash
33+
size_t treesize; /// Total number of compartments from the current node and below
34+
size_t nodevec_index; /// index in nodevec that is set in check()
35+
/// In cell permute 2 this is set as Breadth First traversal
36+
size_t treenode_order; /// For cell permute 1 (Interleaved):
37+
/// - This is the id given to the compartments based on a Breadth First
38+
/// access on the tree that is created in the original circuit
39+
/// - This is what makes the cell ordering interleaved
40+
/// For cell permute 2 (Constant Depth):
41+
/// VVVTN: Vector (groups of cells) of vector (levels of this group of
42+
/// cells. Maxsize = maxlevel) of vector of TNodes This changes 3 times
43+
/// during cell permute 2:
44+
/// 1. According to the sorting of the nodes of each level
45+
/// 2. According to the sorting of the parents' treenode_order of the
46+
/// previous ordering
47+
/// 3. According to children and parents data races. Parents and
48+
/// children of the tree are moved by question2() so that threads that
49+
/// exist on the same warp don't have data races when updating the
50+
/// children and parent variables, so that threads have to wait in
51+
/// atomic instructions. If there are any races then those are solved by
52+
/// atomic instructions.
53+
size_t level; /// level of of this compartment in the tree
54+
size_t cellindex; /// Cell ID that this compartment belongs to
55+
size_t groupindex; /// Initialized index / groupsize
3456
int nodeindex;
3557
};
3658

coreneuron/permute/cellorder.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -616,7 +616,7 @@ void solve_interleaved2(int ith) {
616616
int ic = icore & (warpsize - 1); // figure out the & mask
617617
int ncycle = ncycles[iwarp];
618618
int* stride = strides + stridedispl[iwarp];
619-
int root = rootbegin[iwarp];
619+
int root = rootbegin[iwarp]; // cell ID -> [0, ncell)
620620
int lastroot = rootbegin[iwarp + 1];
621621
int firstnode = nodebegin[iwarp];
622622
int lastnode = nodebegin[iwarp + 1];

coreneuron/permute/cellorder1.cpp

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -396,6 +396,7 @@ void check(VecTNode& nodevec) {
396396
ncell++;
397397
}
398398
}
399+
/// Check that the first compartments of nodevec are the root nodes (cells)
399400
for (size_t i = 0; i < ncell; ++i) {
400401
nrn_assert(nodevec[i]->parent == nullptr);
401402
}
@@ -543,12 +544,16 @@ static void admin1(int ncell,
543544
}
544545
}
545546

547+
// this vector is used to move from one compartment to the other (per cell)
548+
// its length is equal to the cell with the highest number of compartments
546549
stride = (int*) ecalloc_align(nstride + 1, sizeof(int));
547550
for (int i = 0; i <= nstride; ++i) {
548551
stride[i] = 0;
549552
}
550553
for (size_t i = ncell; i < nodevec.size(); ++i) {
551554
TNode& nd = *nodevec[i];
555+
// compute how many compartments with the same order
556+
// treenode_order : defined in breadth first fashion (for each cell separately)
552557
stride[nd.treenode_order - 1] += 1; // -1 because treenode order includes root
553558
}
554559
}
@@ -590,6 +595,26 @@ static size_t stride_length(size_t begin, size_t end, VecTNode& nodevec) {
590595
return end - begin;
591596
}
592597

598+
/**
599+
* \brief Prepare for solve_interleaved2
600+
*
601+
* One group of cells per warp.
602+
*
603+
* warp[i] has a number of compute cycles (ncycle[i])
604+
* the index of its first root (rootbegin[i], last rootbegin[nwarp] = ncell)
605+
* the index of its first node (nodebegin[i], last nodebegin[nwarp] = nnode)
606+
*
607+
* Each compute cycle has a stride
608+
* A stride is how many nodes are processed by a warp in one compute cycle
609+
* There are nstride strides. nstride is the sum of ncycles of all warps.
610+
* warp[i] has ncycle[i] strides
611+
* same as sum of ncycle
612+
* warp[i] has a stridedispl[i] which is stridedispl[i-1] + ncycle[i].
613+
* ie. The zeroth cycle of warp[j] works on stride[stridedispl[j]]
614+
* The value of a stride beginning at node i (node i is computed by core 0 of
615+
* some warp for some cycle) is determined by stride_length(i, j, nodevec)
616+
*
617+
*/
593618
static void admin2(int ncell,
594619
VecTNode& nodevec,
595620
int& nwarp,
@@ -628,6 +653,7 @@ static void admin2(int ncell,
628653
size_t j = size_t(nodebegin[iwarp + 1]);
629654
int nc = 0;
630655
size_t i = nodebegin[iwarp];
656+
// in this loop we traverse all the children of all the cells in the current warp (iwarp)
631657
while (i < j) {
632658
i += stride_length(i, j, nodevec);
633659
++nc; // how many times the warp should loop in order to finish with all the tree

coreneuron/permute/cellorder2.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ static void sortlevel(VTN& level) {
6969
}
7070
}
7171

72+
// TODO: refactor since sortlevel() is traversing the nodes in same order
7273
static void set_treenode_order(VVTN& levels) {
7374
size_t order = 0;
7475
for (auto& level: levels) {
@@ -344,8 +345,8 @@ static void question2(VVTN& levels) {
344345
// belong to separate warps
345346

346347
// work backward and check the distance from parent to children.
347-
// if parent in different group then there is no vitiating race.
348-
// if children in different group then ther is no race (satisfied by
348+
// if parent in different group (warp?) then there is no vitiating race.
349+
// if children in different group (warp?) then ther is no race (satisfied by
349350
// atomic).
350351
// If there is a vitiating race, then figure out how many nodes
351352
// need to be inserted just before the parent to avoid the race.

0 commit comments

Comments
 (0)