Skip to content

Commit dad09cb

Browse files
authored
Add additional mbarrier instruction and SASS mapping (#83)
1 parent 80f1acd commit dad09cb

1 file changed

Lines changed: 135 additions & 21 deletions

File tree

  • src/cuda/GPU_Microbenchmark/ubench/tma/mbarrier

src/cuda/GPU_Microbenchmark/ubench/tma/mbarrier/mbarrier.cu

Lines changed: 135 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -30,57 +30,112 @@ namespace ptx = cuda::ptx;
3030
} \
3131
}
3232

33-
__global__ __noinline__ void test_mbarrier_kernel() {
33+
__global__ __noinline__ void test_mbarrier_kernel(uint64_t *sink) {
3434
// mbarrier object is 64bit in shared memory
3535
__shared__ uint64_t mbarrier;
3636
uint64_t state;
3737
int32_t count;
3838
// Initialize the mbarrier with PTX asm
3939
int block_size = blockDim.x * blockDim.y;
4040
if (threadIdx.x == 0 && threadIdx.y == 0) {
41-
asm("mbarrier.init.shared::cta.b64 [%0], %1;" : : "l"(&mbarrier), "r"(block_size) : "memory");
41+
asm("mbarrier.init.shared::cta.b64 [%0], %1;" : : "l"(&mbarrier), "r"(0x1234) : "memory");
4242
}
4343
__syncthreads();
4444

4545
// Expect on the mbarrier
4646
#if __CUDA_ARCH__ >= 900
4747
int bytes_per_thread = 4;
48+
asm("barrier.sync 0;");
49+
// SYNCS.ARRIVE.TRANS64.RED.A0TR
4850
asm("mbarrier.expect_tx.shared::cta.b64 [%0], %1;" : : "l"(&mbarrier), "r"(bytes_per_thread) : "memory");
49-
__syncthreads();
51+
asm("mbarrier.expect_tx.shared::cluster.b64 [%0], %1;" : : "l"(&mbarrier), "r"(2*bytes_per_thread) : "memory");
5052

5153
// Complete on the mbarrier
52-
asm("mbarrier.complete_tx.shared::cta.b64 [%0], %1;" : : "l"(&mbarrier), "r"(bytes_per_thread) : "memory");
53-
__syncthreads();
54+
asm("barrier.sync 1;");
55+
// SYNCS.ARRIVE.TRANS64.RED.A0TX
56+
asm("mbarrier.complete_tx.shared::cta.b64 [%0], %1;" : : "l"(&mbarrier), "r"(3*bytes_per_thread) : "memory");
5457

5558
// All threads in the block arrive on the mbarrier
56-
asm("mbarrier.arrive.b64 %0, [%1], %2;" : "=l"(state) : "l"(&mbarrier), "n"(1) : "memory");
57-
__syncthreads();
59+
asm("barrier.sync 2;");
60+
// SYNCS.ARRIVE.TRANS64.RED.A1T0 (no count specified, return value is not used)
61+
asm("mbarrier.arrive.b64 %0, [%1];" : "=l"(state) : "l"(&mbarrier) : "memory");
62+
asm("mbarrier.arrive.b64 _, [%0];" :: "l"(&mbarrier) : "memory");
63+
// SYNCS.ARRIVE.TRANS64.A1T0 (return value is used)
64+
asm("mbarrier.arrive.b64 %0, [%1];" : "=l"(state) : "l"(&mbarrier) : "memory");
65+
*sink += state;
66+
// SYNCS.ARRIVE.TRANS64.RED.ART0 (return value state is not used)
67+
asm("mbarrier.arrive.b64 %0, [%1], %2;" : "=l"(state) : "l"(&mbarrier), "n"(4) : "memory");
68+
asm("mbarrier.arrive.b64 _ , [%0], %1;" : : "l"(&mbarrier), "n"(4) : "memory");
69+
// SYNCS.ARRIVE.TRANS64.ART0 (return value state is used)
70+
asm("mbarrier.arrive.b64 %0, [%1], %2;" : "=l"(state) : "l"(&mbarrier), "n"(5) : "memory");
71+
*sink += state;
72+
73+
// ARRIVE with no complete
74+
asm("barrier.sync 3;");
75+
// SYNCS.ARRIVE.TRANS64.RED.ART0
76+
asm("mbarrier.arrive.noComplete.b64 %0, [%1], %2;" : "=l"(state) : "l"(&mbarrier), "n"(5) : "memory");
77+
// SYNCS.ARRIVE.TRANS64.TMASK.ART0 (return value is used)
78+
asm("mbarrier.arrive.noComplete.b64 %0, [%1], %2;" : "=l"(state) : "l"(&mbarrier), "n"(6) : "memory");
79+
*sink += state;
5880

5981
// Arrive and expect on the mbarrier
60-
asm("mbarrier.arrive.expect_tx.b64 %0, [%1], %2;" : "=l"(state) : "l"(&mbarrier), "n"(2) : "memory");
61-
__syncthreads();
82+
asm("barrier.sync 4;");
83+
// SYNCS.ARRIVE.TRANS64.RED (return value is not used)
84+
asm("mbarrier.arrive.expect_tx.b64 %0, [%1], %2;" : "=l"(state) : "l"(&mbarrier), "n"(6) : "memory");
85+
asm("mbarrier.arrive.expect_tx.b64 _, [%0], %1;" :: "l"(&mbarrier), "n"(6) : "memory");
86+
// SYNCS.ARRIVE.TRANS64 (return value is used)
87+
asm("mbarrier.arrive.expect_tx.b64 %0, [%1], %2;" : "=l"(state) : "l"(&mbarrier), "n"(6) : "memory");
88+
*sink += state;
6289

6390
// Arrive and drop
91+
asm("barrier.sync 5;");
92+
// SYNCS.ARRIVE.TRANS64.RED.OPTOUT.A1T0 (not using return value)
93+
asm("mbarrier.arrive_drop.b64 %0, [%1];" : "=l"(state) : "l"(&mbarrier) : "memory");
94+
asm("mbarrier.arrive_drop.b64 _, [%0];" :: "l"(&mbarrier) : "memory");
95+
// SYNCS.ARRIVE.TRANS64.OPTOUT.A1T0 (using return value)
96+
asm("mbarrier.arrive_drop.b64 %0, [%1];" : "=l"(state) : "l"(&mbarrier) : "memory");
97+
*sink += state;
98+
99+
// SYNCS.ARRIVE.TRANS64.RED.OPTOUT.ART0 (not using return value)
64100
asm("mbarrier.arrive_drop.b64 %0, [%1], %2;" : "=l"(state) : "l"(&mbarrier), "n"(3) : "memory");
65-
__syncthreads();
101+
asm("mbarrier.arrive_drop.b64 _, [%0], %1;" :: "l"(&mbarrier), "n"(3) : "memory");
102+
// SYNCS.ARRIVE.TRANS64.OPTOUT.ART0 (using return value)
103+
asm("mbarrier.arrive_drop.b64 %0, [%1], %2;" : "=l"(state) : "l"(&mbarrier), "n"(3) : "memory");
104+
*sink += state;
105+
106+
asm("barrier.sync 6;");
107+
// SYNCS.ARRIVE.TRANS64.RED.OPTOUT.ART0
108+
asm("mbarrier.arrive_drop.noComplete.b64 %0, [%1], %2;" : "=l"(state) : "l"(&mbarrier), "n"(3) : "memory");
109+
asm("mbarrier.arrive_drop.noComplete.b64 _, [%0], %1;" :: "l"(&mbarrier), "n"(3) : "memory");
110+
// SYNCS.ARRIVE.TRANS64.TMASK.OPTOUT.ART0
111+
asm("mbarrier.arrive_drop.noComplete.b64 %0, [%1], %2;" : "=l"(state) : "l"(&mbarrier), "n"(3) : "memory");
112+
*sink += state;
113+
66114
#else
67115
// For sm_80
68116
// All threads in the block arrive on the mbarrier
117+
asm("barrier.sync 5;");
69118
asm("mbarrier.arrive.noComplete.b64 %0, [%1], %2;" : "=l"(state) : "l"(&mbarrier), "n"(1) : "memory");
70-
__syncthreads();
71119

72-
// Arrive and drop
120+
// Arrive and drop with no complete
121+
asm("barrier.sync 6;");
73122
asm("mbarrier.arrive_drop.noComplete.b64 %0, [%1], %2;" : "=l"(state) : "l"(&mbarrier), "n"(3) : "memory");
74-
__syncthreads();
75123
#endif
76124

77125
#if __CUDA_ARCH__ >= 900
78-
// Arrive and drop
126+
// Arrive and drop expect tx
127+
asm("barrier.sync 7;");
128+
// SYNCS.ARRIVE.TRANS64.RED.OPTOUT
79129
asm("mbarrier.arrive_drop.expect_tx.b64 %0, [%1], %2;" : "=l"(state) : "l"(&mbarrier), "n"(4) : "memory");
80-
__syncthreads();
130+
asm("mbarrier.arrive_drop.expect_tx.b64 _, [%0], %1;" :: "l"(&mbarrier), "n"(5) : "memory");
131+
// SYNCS.ARRIVE.TRANS64.OPTOUT RA, [URB], RC; RC is the transaction count
132+
asm("mbarrier.arrive_drop.expect_tx.b64 %0, [%1], %2;" : "=l"(state) : "l"(&mbarrier), "n"(6) : "memory");
133+
*sink += state;
81134
#endif
82135

83136
// Get pending count
137+
asm("barrier.sync 8;");
138+
// This is just a list of arithematic operations on the opaque state variable
84139
asm("mbarrier.pending_count.b64 %0, %1;" : "=r"(count) : "l"(state) : "memory");
85140
// Prevent optimizing away
86141
if (threadIdx.x == 0 && threadIdx.y == 0) {
@@ -89,31 +144,90 @@ __global__ __noinline__ void test_mbarrier_kernel() {
89144
__syncthreads();
90145

91146
// cp async barrier arrive
147+
asm("barrier.sync 9;");
148+
// SYNCS.ARRIVE.TRANS64.RED.A0T1 RZ, [URB], RZ
149+
// ARRIVES.LDGSTSBAR.64.TRANSCNT [URB]
92150
asm("cp.async.mbarrier.arrive.shared::cta.b64 [%0];" : : "l"(&mbarrier) : "memory");
93-
__syncthreads();
151+
asm("barrier.sync 10;");
152+
// ARRIVES.LDGSTSBAR.64.ARVCNT [URB]
94153
asm("cp.async.mbarrier.arrive.noinc.shared::cta.b64 [%0];" : : "l"(&mbarrier) : "memory");
95-
__syncthreads();
96154

97155
// Wait on the mbarrier
98156
#if __CUDA_ARCH__ >= 900
157+
asm("barrier.sync 11;");
158+
// SYNCS.PHASECHK.TRANS64 PT, [UR4], RZ
99159
asm ("\n\t"
100160
".reg .pred complete;\n\t"
101161
"mbarrier.test_wait.parity.b64 complete, [%0], %1;"
102162
: : "l"(&mbarrier), "n"(0) : "memory"
103163
);
104-
__syncthreads();
164+
asm("barrier.sync 12;");
165+
// SYNCS.PHASECHK.TRANS64 PT, [UR4], R0
166+
asm ("\n\t"
167+
"mbarrier.test_wait.parity.b64 complete, [%0], %1;"
168+
: : "l"(&mbarrier), "n"(1) : "memory"
169+
);
170+
asm("barrier.sync 0;");
171+
// SYNCS.PHASECHK.TRANS64.TRYWAIT PT, [UR4], RZ
105172
asm ("\n\t"
106173
"mbarrier.try_wait.parity.b64 complete, [%0], %1;"
107174
: : "l"(&mbarrier), "n"(0) : "memory"
108175
);
176+
asm("barrier.sync 1;");
177+
// SYNCS.PHASECHK.TRANS64.TRYWAIT PT, [UR4], R0
178+
asm ("\n\t"
179+
"mbarrier.try_wait.parity.b64 complete, [%0], %1;"
180+
: : "l"(&mbarrier), "n"(1) : "memory"
181+
);
182+
asm("barrier.sync 2;");
183+
// SYNCS.PHASECHK.TRANS64.TRYWAIT PT, [R4+URZ], RZ
184+
// @!PT NANOSLEEP.SYNCS 0x1234
185+
asm ("\n\t"
186+
"mbarrier.try_wait.parity.b64 complete, [%0], %1, %2;"
187+
: : "l"(&mbarrier), "n"(0), "n"(0x1234) : "memory"
188+
);
189+
asm("barrier.sync 3;");
190+
// SYNCS.PHASECHK.TRANS64.TRYWAIT PT, [R5+URZ], R3
191+
// @!PT NANOSLEEP.SYNCS 0x4321
192+
// @!PT SYNCS.PHASECHK.TRANS64 PT, [R5+URZ], R3 ;
193+
asm ("\n\t"
194+
"mbarrier.try_wait.parity.b64 complete, [%0], %1, %2;"
195+
: : "l"(&mbarrier), "n"(1), "n"(0x4321) : "memory"
196+
);
109197
__syncthreads();
198+
199+
state = 0;
200+
asm("barrier.sync 4;");
201+
// SYNCS.PHASECHK.TRANS64 PT, [UR4], RZ
202+
asm ("\n\t"
203+
".reg .pred complete2;\n\t"
204+
"mbarrier.test_wait.b64 complete2, [%0], %1;"
205+
: : "l"(&mbarrier), "l"(state) : "memory"
206+
);
207+
asm("barrier.sync 5;");
208+
// SYNCS.PHASECHK.TRANS64.TRYWAIT PT, [UR4], RZ
209+
asm ("\n\t"
210+
"mbarrier.try_wait.b64 complete2, [%0], %1;"
211+
: : "l"(&mbarrier), "l"(state) : "memory"
212+
);
213+
asm("barrier.sync 6;");
214+
// SYNCS.PHASECHK.TRANS64.TRYWAIT PT, [R6+URZ], RZ
215+
// @!PT NANOSLEEP.SYNCS 0x1234
216+
// @!PT SYNCS.PHASECHK.TRANS64 PT, [R6+URZ], RZ ;
217+
asm ("\n\t"
218+
"mbarrier.try_wait.b64 complete2, [%0], %1, %2;"
219+
: : "l"(&mbarrier), "l"(state), "n"(0x1234) : "memory"
220+
);
110221
#endif
111222
}
112223

113224
int main(int argc, char *argv[]) {
114-
CUDA_SAFECALL((test_mbarrier_kernel<<<1, 1>>>()));
115-
CUDA_SAFECALL(cudaDeviceSynchronize());
225+
printf("This is a test program mean to compare the mbarrier PTX and SASS mapping, it is not tested at all for functionality/run to finished\n");
226+
// uint64_t *sink;
227+
// cudaMalloc(&sink, sizeof(uint64_t));
228+
// CUDA_SAFECALL((test_mbarrier_kernel<<<1, 1>>>(sink)));
229+
// CUDA_SAFECALL(cudaDeviceSynchronize());
116230

117-
printf("Mbarrier test completed\n");
231+
// printf("Mbarrier test completed\n");
118232
return 0;
119233
}

0 commit comments

Comments
 (0)