Manual block / thread execution order (for reproducible debugging)#
By default blocks and threads run in a RANDOM order (see the header overview) — great for finding order-dependent bugs, but you can’t replay one. Set an explicit order to pin the exact interleaving: simSetThreadOrder(OrderThread{3, 0, 1, 2}); // this permutation, every barrier simSetBlockOrder(OrderBlock::sequential()); // 0,1,2,… (count-agnostic) simResetOrder(); // back to random default The setting is global and persists across launches until changed. OrderBlock and OrderThread are distinct types so the two can’t be swapped by mistake.
Defined in code/simulator.h.
This page documents 20 symbols: 2 classes, 6 constructors, 12 functions.
Classes#
Signature |
Description |
Availability |
Location |
Example |
|---|---|---|---|---|
|
By default blocks and threads run in a RANDOM order (see the header overview) — great for finding order-dependent bugs, but you can’t replay one. |
sim + nvcc |
simulator.h:639 |
|
|
sim + nvcc |
simulator.h:650 |
Constructors#
Signature |
Description |
Availability |
Location |
Example |
|---|---|---|---|---|
|
sim + nvcc |
simulator.h:641 |
||
|
sim + nvcc |
simulator.h:642 |
||
|
sim + nvcc |
simulator.h:643 |
||
|
sim + nvcc |
simulator.h:652 |
||
|
sim + nvcc |
simulator.h:653 |
||
|
sim + nvcc |
simulator.h:654 |
Functions#
Signature |
Description |
Availability |
Location |
Example |
|---|---|---|---|---|
|
sim + nvcc |
simulator.h:648 |
||
|
sim + nvcc |
simulator.h:659 |
||
|
sim + nvcc |
simulator.h:644 |
||
|
sim + nvcc |
simulator.h:655 |
||
|
sim + nvcc |
simulator.h:646 |
||
|
sim + nvcc |
simulator.h:657 |
||
|
sim + nvcc |
simulator.h:645 |
||
|
sim + nvcc |
simulator.h:656 |
||
|
sim + nvcc |
simulator.h:673 |
||
|
Runtime setters — call before a LAUNCH (or between launches) to pin ordering. |
sim + nvcc |
simulator.h:668 |
|
|
sim + nvcc |
simulator.h:670 |
||
|
sim + nvcc |
simulator.h:669 |
Examples#
Code from the repository’s example corpus (code\*.cu); the highlighted line is the call site. These blocks are what the View links above open.
OrderBlock (test_order.cu:153)
143 // ---- Block order ---------------------------------------------------------
144 {
145 simSetBlockOrder(OrderBlock::reverse());
146 std::vector<int> out = runBlocks(GRID);
147 std::vector<int> rev(GRID); for (int i = 0; i < GRID; ++i) rev[i] = GRID - 1 - i;
148 bool ok = isPermutation(out) && (!onSim || matchesOrder(out, rev));
149 all &= report("block order: reverse", ok);
150 }
151 {
152 std::vector<int> perm = {5, 2, 7, 0, 3, 6, 1, 4};
153 simSetBlockOrder(OrderBlock(perm));
154 std::vector<int> out = runBlocks(GRID);
155 bool ok = isPermutation(out) && (!onSim || matchesOrder(out, perm));
156 all &= report("block order: custom {5,2,7,0,3,6,1,4}", ok);
157 }
158
159 // ---- Reset restores the random default -----------------------------------
160 {
161 simResetOrder();
162 std::vector<int> t = runThreads(BLOCK);
163 std::vector<int> b = runBlocks(GRID);
164 all &= report("reset -> random default (valid perms)",
OrderThread (test_order.cu:124)
114 // ---- Thread order --------------------------------------------------------
115 {
116 simSetThreadOrder(OrderThread::sequential());
117 std::vector<int> out = runThreads(BLOCK);
118 std::vector<int> seq(BLOCK); for (int i = 0; i < BLOCK; ++i) seq[i] = i;
119 bool ok = isPermutation(out) && (!onSim || matchesOrder(out, seq));
120 all &= report("thread order: sequential", ok);
121 }
122 {
123 std::vector<int> perm = {3, 0, 1, 2, 7, 4, 5, 6}; // explicit permutation
124 simSetThreadOrder(OrderThread(perm));
125 std::vector<int> out = runThreads(BLOCK);
126 bool ok = isPermutation(out) && (!onSim || matchesOrder(out, perm));
127 all &= report("thread order: custom {3,0,1,2,7,4,5,6}", ok);
128 }
129 {
130 simSetThreadOrder(OrderThread::reverse());
131 std::vector<int> out = runThreads(BLOCK);
132 std::vector<int> rev(BLOCK); for (int i = 0; i < BLOCK; ++i) rev[i] = BLOCK - 1 - i;
133 bool ok = isPermutation(out) && (!onSim || matchesOrder(out, rev));
134 all &= report("thread order: reverse", ok);
135 }
OrderBlock (test_order.cu:153)
143 // ---- Block order ---------------------------------------------------------
144 {
145 simSetBlockOrder(OrderBlock::reverse());
146 std::vector<int> out = runBlocks(GRID);
147 std::vector<int> rev(GRID); for (int i = 0; i < GRID; ++i) rev[i] = GRID - 1 - i;
148 bool ok = isPermutation(out) && (!onSim || matchesOrder(out, rev));
149 all &= report("block order: reverse", ok);
150 }
151 {
152 std::vector<int> perm = {5, 2, 7, 0, 3, 6, 1, 4};
153 simSetBlockOrder(OrderBlock(perm));
154 std::vector<int> out = runBlocks(GRID);
155 bool ok = isPermutation(out) && (!onSim || matchesOrder(out, perm));
156 all &= report("block order: custom {5,2,7,0,3,6,1,4}", ok);
157 }
158
159 // ---- Reset restores the random default -----------------------------------
160 {
161 simResetOrder();
162 std::vector<int> t = runThreads(BLOCK);
163 std::vector<int> b = runBlocks(GRID);
164 all &= report("reset -> random default (valid perms)",
OrderBlock (test_order.cu:153)
143 // ---- Block order ---------------------------------------------------------
144 {
145 simSetBlockOrder(OrderBlock::reverse());
146 std::vector<int> out = runBlocks(GRID);
147 std::vector<int> rev(GRID); for (int i = 0; i < GRID; ++i) rev[i] = GRID - 1 - i;
148 bool ok = isPermutation(out) && (!onSim || matchesOrder(out, rev));
149 all &= report("block order: reverse", ok);
150 }
151 {
152 std::vector<int> perm = {5, 2, 7, 0, 3, 6, 1, 4};
153 simSetBlockOrder(OrderBlock(perm));
154 std::vector<int> out = runBlocks(GRID);
155 bool ok = isPermutation(out) && (!onSim || matchesOrder(out, perm));
156 all &= report("block order: custom {5,2,7,0,3,6,1,4}", ok);
157 }
158
159 // ---- Reset restores the random default -----------------------------------
160 {
161 simResetOrder();
162 std::vector<int> t = runThreads(BLOCK);
163 std::vector<int> b = runBlocks(GRID);
164 all &= report("reset -> random default (valid perms)",
OrderBlock (test_order.cu:153)
143 // ---- Block order ---------------------------------------------------------
144 {
145 simSetBlockOrder(OrderBlock::reverse());
146 std::vector<int> out = runBlocks(GRID);
147 std::vector<int> rev(GRID); for (int i = 0; i < GRID; ++i) rev[i] = GRID - 1 - i;
148 bool ok = isPermutation(out) && (!onSim || matchesOrder(out, rev));
149 all &= report("block order: reverse", ok);
150 }
151 {
152 std::vector<int> perm = {5, 2, 7, 0, 3, 6, 1, 4};
153 simSetBlockOrder(OrderBlock(perm));
154 std::vector<int> out = runBlocks(GRID);
155 bool ok = isPermutation(out) && (!onSim || matchesOrder(out, perm));
156 all &= report("block order: custom {5,2,7,0,3,6,1,4}", ok);
157 }
158
159 // ---- Reset restores the random default -----------------------------------
160 {
161 simResetOrder();
162 std::vector<int> t = runThreads(BLOCK);
163 std::vector<int> b = runBlocks(GRID);
164 all &= report("reset -> random default (valid perms)",
OrderThread (test_order.cu:124)
114 // ---- Thread order --------------------------------------------------------
115 {
116 simSetThreadOrder(OrderThread::sequential());
117 std::vector<int> out = runThreads(BLOCK);
118 std::vector<int> seq(BLOCK); for (int i = 0; i < BLOCK; ++i) seq[i] = i;
119 bool ok = isPermutation(out) && (!onSim || matchesOrder(out, seq));
120 all &= report("thread order: sequential", ok);
121 }
122 {
123 std::vector<int> perm = {3, 0, 1, 2, 7, 4, 5, 6}; // explicit permutation
124 simSetThreadOrder(OrderThread(perm));
125 std::vector<int> out = runThreads(BLOCK);
126 bool ok = isPermutation(out) && (!onSim || matchesOrder(out, perm));
127 all &= report("thread order: custom {3,0,1,2,7,4,5,6}", ok);
128 }
129 {
130 simSetThreadOrder(OrderThread::reverse());
131 std::vector<int> out = runThreads(BLOCK);
132 std::vector<int> rev(BLOCK); for (int i = 0; i < BLOCK; ++i) rev[i] = BLOCK - 1 - i;
133 bool ok = isPermutation(out) && (!onSim || matchesOrder(out, rev));
134 all &= report("thread order: reverse", ok);
135 }
OrderThread (test_order.cu:124)
114 // ---- Thread order --------------------------------------------------------
115 {
116 simSetThreadOrder(OrderThread::sequential());
117 std::vector<int> out = runThreads(BLOCK);
118 std::vector<int> seq(BLOCK); for (int i = 0; i < BLOCK; ++i) seq[i] = i;
119 bool ok = isPermutation(out) && (!onSim || matchesOrder(out, seq));
120 all &= report("thread order: sequential", ok);
121 }
122 {
123 std::vector<int> perm = {3, 0, 1, 2, 7, 4, 5, 6}; // explicit permutation
124 simSetThreadOrder(OrderThread(perm));
125 std::vector<int> out = runThreads(BLOCK);
126 bool ok = isPermutation(out) && (!onSim || matchesOrder(out, perm));
127 all &= report("thread order: custom {3,0,1,2,7,4,5,6}", ok);
128 }
129 {
130 simSetThreadOrder(OrderThread::reverse());
131 std::vector<int> out = runThreads(BLOCK);
132 std::vector<int> rev(BLOCK); for (int i = 0; i < BLOCK; ++i) rev[i] = BLOCK - 1 - i;
133 bool ok = isPermutation(out) && (!onSim || matchesOrder(out, rev));
134 all &= report("thread order: reverse", ok);
135 }
OrderThread (test_order.cu:124)
114 // ---- Thread order --------------------------------------------------------
115 {
116 simSetThreadOrder(OrderThread::sequential());
117 std::vector<int> out = runThreads(BLOCK);
118 std::vector<int> seq(BLOCK); for (int i = 0; i < BLOCK; ++i) seq[i] = i;
119 bool ok = isPermutation(out) && (!onSim || matchesOrder(out, seq));
120 all &= report("thread order: sequential", ok);
121 }
122 {
123 std::vector<int> perm = {3, 0, 1, 2, 7, 4, 5, 6}; // explicit permutation
124 simSetThreadOrder(OrderThread(perm));
125 std::vector<int> out = runThreads(BLOCK);
126 bool ok = isPermutation(out) && (!onSim || matchesOrder(out, perm));
127 all &= report("thread order: custom {3,0,1,2,7,4,5,6}", ok);
128 }
129 {
130 simSetThreadOrder(OrderThread::reverse());
131 std::vector<int> out = runThreads(BLOCK);
132 std::vector<int> rev(BLOCK); for (int i = 0; i < BLOCK; ++i) rev[i] = BLOCK - 1 - i;
133 bool ok = isPermutation(out) && (!onSim || matchesOrder(out, rev));
134 all &= report("thread order: reverse", ok);
135 }
OrderBlock (test_order.cu:153)
143 // ---- Block order ---------------------------------------------------------
144 {
145 simSetBlockOrder(OrderBlock::reverse());
146 std::vector<int> out = runBlocks(GRID);
147 std::vector<int> rev(GRID); for (int i = 0; i < GRID; ++i) rev[i] = GRID - 1 - i;
148 bool ok = isPermutation(out) && (!onSim || matchesOrder(out, rev));
149 all &= report("block order: reverse", ok);
150 }
151 {
152 std::vector<int> perm = {5, 2, 7, 0, 3, 6, 1, 4};
153 simSetBlockOrder(OrderBlock(perm));
154 std::vector<int> out = runBlocks(GRID);
155 bool ok = isPermutation(out) && (!onSim || matchesOrder(out, perm));
156 all &= report("block order: custom {5,2,7,0,3,6,1,4}", ok);
157 }
158
159 // ---- Reset restores the random default -----------------------------------
160 {
161 simResetOrder();
162 std::vector<int> t = runThreads(BLOCK);
163 std::vector<int> b = runBlocks(GRID);
164 all &= report("reset -> random default (valid perms)",
OrderThread (test_order.cu:124)
114 // ---- Thread order --------------------------------------------------------
115 {
116 simSetThreadOrder(OrderThread::sequential());
117 std::vector<int> out = runThreads(BLOCK);
118 std::vector<int> seq(BLOCK); for (int i = 0; i < BLOCK; ++i) seq[i] = i;
119 bool ok = isPermutation(out) && (!onSim || matchesOrder(out, seq));
120 all &= report("thread order: sequential", ok);
121 }
122 {
123 std::vector<int> perm = {3, 0, 1, 2, 7, 4, 5, 6}; // explicit permutation
124 simSetThreadOrder(OrderThread(perm));
125 std::vector<int> out = runThreads(BLOCK);
126 bool ok = isPermutation(out) && (!onSim || matchesOrder(out, perm));
127 all &= report("thread order: custom {3,0,1,2,7,4,5,6}", ok);
128 }
129 {
130 simSetThreadOrder(OrderThread::reverse());
131 std::vector<int> out = runThreads(BLOCK);
132 std::vector<int> rev(BLOCK); for (int i = 0; i < BLOCK; ++i) rev[i] = BLOCK - 1 - i;
133 bool ok = isPermutation(out) && (!onSim || matchesOrder(out, rev));
134 all &= report("thread order: reverse", ok);
135 }
random (test_order.cu:137)
127 all &= report("thread order: custom {3,0,1,2,7,4,5,6}", ok);
128 }
129 {
130 simSetThreadOrder(OrderThread::reverse());
131 std::vector<int> out = runThreads(BLOCK);
132 std::vector<int> rev(BLOCK); for (int i = 0; i < BLOCK; ++i) rev[i] = BLOCK - 1 - i;
133 bool ok = isPermutation(out) && (!onSim || matchesOrder(out, rev));
134 all &= report("thread order: reverse", ok);
135 }
136 {
137 simSetThreadOrder(OrderThread::random());
138 simSetSeed(7);
139 std::vector<int> out = runThreads(BLOCK);
140 all &= report("thread order: random is a permutation", isPermutation(out));
141 }
142
143 // ---- Block order ---------------------------------------------------------
144 {
145 simSetBlockOrder(OrderBlock::reverse());
146 std::vector<int> out = runBlocks(GRID);
147 std::vector<int> rev(GRID); for (int i = 0; i < GRID; ++i) rev[i] = GRID - 1 - i;
148 bool ok = isPermutation(out) && (!onSim || matchesOrder(out, rev));
random (test_order.cu:137)
127 all &= report("thread order: custom {3,0,1,2,7,4,5,6}", ok);
128 }
129 {
130 simSetThreadOrder(OrderThread::reverse());
131 std::vector<int> out = runThreads(BLOCK);
132 std::vector<int> rev(BLOCK); for (int i = 0; i < BLOCK; ++i) rev[i] = BLOCK - 1 - i;
133 bool ok = isPermutation(out) && (!onSim || matchesOrder(out, rev));
134 all &= report("thread order: reverse", ok);
135 }
136 {
137 simSetThreadOrder(OrderThread::random());
138 simSetSeed(7);
139 std::vector<int> out = runThreads(BLOCK);
140 all &= report("thread order: random is a permutation", isPermutation(out));
141 }
142
143 // ---- Block order ---------------------------------------------------------
144 {
145 simSetBlockOrder(OrderBlock::reverse());
146 std::vector<int> out = runBlocks(GRID);
147 std::vector<int> rev(GRID); for (int i = 0; i < GRID; ++i) rev[i] = GRID - 1 - i;
148 bool ok = isPermutation(out) && (!onSim || matchesOrder(out, rev));
reverse (test_order.cu:130)
120 all &= report("thread order: sequential", ok);
121 }
122 {
123 std::vector<int> perm = {3, 0, 1, 2, 7, 4, 5, 6}; // explicit permutation
124 simSetThreadOrder(OrderThread(perm));
125 std::vector<int> out = runThreads(BLOCK);
126 bool ok = isPermutation(out) && (!onSim || matchesOrder(out, perm));
127 all &= report("thread order: custom {3,0,1,2,7,4,5,6}", ok);
128 }
129 {
130 simSetThreadOrder(OrderThread::reverse());
131 std::vector<int> out = runThreads(BLOCK);
132 std::vector<int> rev(BLOCK); for (int i = 0; i < BLOCK; ++i) rev[i] = BLOCK - 1 - i;
133 bool ok = isPermutation(out) && (!onSim || matchesOrder(out, rev));
134 all &= report("thread order: reverse", ok);
135 }
136 {
137 simSetThreadOrder(OrderThread::random());
138 simSetSeed(7);
139 std::vector<int> out = runThreads(BLOCK);
140 all &= report("thread order: random is a permutation", isPermutation(out));
141 }
reverse (test_order.cu:130)
120 all &= report("thread order: sequential", ok);
121 }
122 {
123 std::vector<int> perm = {3, 0, 1, 2, 7, 4, 5, 6}; // explicit permutation
124 simSetThreadOrder(OrderThread(perm));
125 std::vector<int> out = runThreads(BLOCK);
126 bool ok = isPermutation(out) && (!onSim || matchesOrder(out, perm));
127 all &= report("thread order: custom {3,0,1,2,7,4,5,6}", ok);
128 }
129 {
130 simSetThreadOrder(OrderThread::reverse());
131 std::vector<int> out = runThreads(BLOCK);
132 std::vector<int> rev(BLOCK); for (int i = 0; i < BLOCK; ++i) rev[i] = BLOCK - 1 - i;
133 bool ok = isPermutation(out) && (!onSim || matchesOrder(out, rev));
134 all &= report("thread order: reverse", ok);
135 }
136 {
137 simSetThreadOrder(OrderThread::random());
138 simSetSeed(7);
139 std::vector<int> out = runThreads(BLOCK);
140 all &= report("thread order: random is a permutation", isPermutation(out));
141 }
sequential (test_debug.cu:92)
82 false;
83#else
84 true;
85#endif
86
87 // The hook: break at the 2nd reduction (segment 2), print the block/segment,
88 // and reorder the threads for that reduction only.
89 const std::vector<int> custom = {3, 0, 1, 2, 7, 4, 5, 6};
90 std::vector<int> segmentsSeen;
91
92 simSetThreadOrder(OrderThread::sequential()); // default order for all segments
93 simSetStepHook([&](SimDebug& d) {
94 segmentsSeen.push_back(d.segment());
95 if (d.segment() == 2) {
96 std::printf(" [hook] break at block %u, segment %d (2nd reduction): "
97 "reorder threads -> {3,0,1,2,7,4,5,6}\n", d.block(), d.segment());
98 d.setThreadOrder(custom);
99 }
100 });
101
102 std::vector<int> rank = run();
103 simClearStepHook();
sequential (test_debug.cu:92)
82 false;
83#else
84 true;
85#endif
86
87 // The hook: break at the 2nd reduction (segment 2), print the block/segment,
88 // and reorder the threads for that reduction only.
89 const std::vector<int> custom = {3, 0, 1, 2, 7, 4, 5, 6};
90 std::vector<int> segmentsSeen;
91
92 simSetThreadOrder(OrderThread::sequential()); // default order for all segments
93 simSetStepHook([&](SimDebug& d) {
94 segmentsSeen.push_back(d.segment());
95 if (d.segment() == 2) {
96 std::printf(" [hook] break at block %u, segment %d (2nd reduction): "
97 "reorder threads -> {3,0,1,2,7,4,5,6}\n", d.block(), d.segment());
98 d.setThreadOrder(custom);
99 }
100 });
101
102 std::vector<int> rank = run();
103 simClearStepHook();
simResetOrder (test_order.cu:161)
151 {
152 std::vector<int> perm = {5, 2, 7, 0, 3, 6, 1, 4};
153 simSetBlockOrder(OrderBlock(perm));
154 std::vector<int> out = runBlocks(GRID);
155 bool ok = isPermutation(out) && (!onSim || matchesOrder(out, perm));
156 all &= report("block order: custom {5,2,7,0,3,6,1,4}", ok);
157 }
158
159 // ---- Reset restores the random default -----------------------------------
160 {
161 simResetOrder();
162 std::vector<int> t = runThreads(BLOCK);
163 std::vector<int> b = runBlocks(GRID);
164 all &= report("reset -> random default (valid perms)",
165 isPermutation(t) && isPermutation(b));
166 }
167
168 // ---- Determinism: same pinned order twice -> identical visit order -------
169 {
170 simSetThreadOrder(OrderThread({2, 5, 1, 0, 7, 3, 6, 4}));
171 std::vector<int> a = runThreads(BLOCK);
172 std::vector<int> b = runThreads(BLOCK);
simSetBlockOrder (test_order.cu:145)
135 }
136 {
137 simSetThreadOrder(OrderThread::random());
138 simSetSeed(7);
139 std::vector<int> out = runThreads(BLOCK);
140 all &= report("thread order: random is a permutation", isPermutation(out));
141 }
142
143 // ---- Block order ---------------------------------------------------------
144 {
145 simSetBlockOrder(OrderBlock::reverse());
146 std::vector<int> out = runBlocks(GRID);
147 std::vector<int> rev(GRID); for (int i = 0; i < GRID; ++i) rev[i] = GRID - 1 - i;
148 bool ok = isPermutation(out) && (!onSim || matchesOrder(out, rev));
149 all &= report("block order: reverse", ok);
150 }
151 {
152 std::vector<int> perm = {5, 2, 7, 0, 3, 6, 1, 4};
153 simSetBlockOrder(OrderBlock(perm));
154 std::vector<int> out = runBlocks(GRID);
155 bool ok = isPermutation(out) && (!onSim || matchesOrder(out, perm));
156 all &= report("block order: custom {5,2,7,0,3,6,1,4}", ok);
simSetThreadOrder (test_debug.cu:92)
82 false;
83#else
84 true;
85#endif
86
87 // The hook: break at the 2nd reduction (segment 2), print the block/segment,
88 // and reorder the threads for that reduction only.
89 const std::vector<int> custom = {3, 0, 1, 2, 7, 4, 5, 6};
90 std::vector<int> segmentsSeen;
91
92 simSetThreadOrder(OrderThread::sequential()); // default order for all segments
93 simSetStepHook([&](SimDebug& d) {
94 segmentsSeen.push_back(d.segment());
95 if (d.segment() == 2) {
96 std::printf(" [hook] break at block %u, segment %d (2nd reduction): "
97 "reorder threads -> {3,0,1,2,7,4,5,6}\n", d.block(), d.segment());
98 d.setThreadOrder(custom);
99 }
100 });
101
102 std::vector<int> rank = run();
103 simClearStepHook();