When compiling the following code for sm_90a architecture, PTXAS complains that number of registers is not enough for wgmma.mma_async(need 154, but actual 128), which is very strange since there’s already a setmaxnreg instruction which increase the regcount from 128 to 200.
__launch_bounds__(512, 1)
__global__ void kernel(const char *input_s8, const char *weight_s8, int *output,
unsigned infeaturesdiv128) {
extern __shared__ char buffer[];
char *buf = &buffer[0];
asm ("cvta.to.shared.u64 %0,%0;\n":"+l"(buf));
//blockDim.x == 128, blockDim.y == 4, blockDim.z == 1, gridDim.z == 8
//barrier initialization omitted
if (threadIdx.y < 2) {
/* consumer: 2 warpgroups */
asm volatile ("setmaxnreg.inc.sync.aligned.u32 200;\n":::"memory");
auto mdenc = [](size_t x)->size_t { return (x & 0x3FFFF) >> 4; };
const size_t mdbase_inp = (mdenc(1024) << 16) | (mdenc(128) << 32);
const size_t mdbase_wt = (mdenc(128) << 16) | (mdenc(1024) << 32);
int acc[128] = {};
asm volatile ("wgmma.fence.sync.aligned;\n":::"memory");
int buffer_id = 0;
auto commit_k128 = [&]()->void {
size_t baseaddr = reinterpret_cast<size_t>(buf) + buffer_id * 384 * 128;
size_t input_addr = baseaddr + threadIdx.y * 8192;
size_t md_input = mdbase_inp | mdenc(input_addr);
size_t wt_addr = baseaddr + 16384;
size_t md_weight1 = mdbase_wt | mdenc(wt_addr);
for (int i = 0; i < 4; ++i) {
asm ("wgmma.mma_async.sync.aligned.m64n256k32.s32.s8.s8 "
"{%0,%1,%2,%3,%4,%5,%6,%7,%8,%9,%10,%11,%12,%13,%14,%15,%16,%17,%18,"
"%19,%20,%21,%22,%23,%24,%25,%26,%27,%28,%29,%30,%31,%32,%33,%34,%35,"
"%36,%37,%38,%39,%40,%41,%42,%43,%44,%45,%46,%47,%48,%49,%50,%51,%52,"
"%53,%54,%55,%56,%57,%58,%59,%60,%61,%62,%63,%64,%65,%66,%67,%68,%69,"
"%70,%71,%72,%73,%74,%75,%76,%77,%78,%79,%80,%81,%82,%83,%84,%85,%86,"
"%87,%88,%89,%90,%91,%92,%93,%94,%95,%96,%97,%98,%99,%100,%101,%102,"
"%103,%104,%105,%106,%107,%108,%109,%110,%111,%112,%113,%114,%115,"
"%116,%117,%118,%119,%120,%121,%122,%123,%124,%125,%126,%127},%128,%129,1;\n"
:"+r"(acc[0]),"+r"(acc[1]),"+r"(acc[2]),"+r"(acc[3]),"+r"(acc[4]),
"+r"(acc[5]),"+r"(acc[6]),"+r"(acc[7]),"+r"(acc[8]),"+r"(acc[9]),
"+r"(acc[10]),"+r"(acc[11]),"+r"(acc[12]),"+r"(acc[13]),"+r"(acc[14]),
"+r"(acc[15]),"+r"(acc[16]),"+r"(acc[17]),"+r"(acc[18]),"+r"(acc[19]),
"+r"(acc[20]),"+r"(acc[21]),"+r"(acc[22]),"+r"(acc[23]),"+r"(acc[24]),
"+r"(acc[25]),"+r"(acc[26]),"+r"(acc[27]),"+r"(acc[28]),"+r"(acc[29]),
"+r"(acc[30]),"+r"(acc[31]),"+r"(acc[32]),"+r"(acc[33]),"+r"(acc[34]),
"+r"(acc[35]),"+r"(acc[36]),"+r"(acc[37]),"+r"(acc[38]),"+r"(acc[39]),
"+r"(acc[40]),"+r"(acc[41]),"+r"(acc[42]),"+r"(acc[43]),"+r"(acc[44]),
"+r"(acc[45]),"+r"(acc[46]),"+r"(acc[47]),"+r"(acc[48]),"+r"(acc[49]),
"+r"(acc[50]),"+r"(acc[51]),"+r"(acc[52]),"+r"(acc[53]),"+r"(acc[54]),
"+r"(acc[55]),"+r"(acc[56]),"+r"(acc[57]),"+r"(acc[58]),"+r"(acc[59]),
"+r"(acc[60]),"+r"(acc[61]),"+r"(acc[62]),"+r"(acc[63]),
"+r"(acc[64]),"+r"(acc[65]),"+r"(acc[66]),"+r"(acc[67]),"+r"(acc[68]),
"+r"(acc[69]),"+r"(acc[70]),"+r"(acc[71]),"+r"(acc[72]),"+r"(acc[73]),
"+r"(acc[74]),"+r"(acc[75]),"+r"(acc[76]),"+r"(acc[77]),"+r"(acc[78]),
"+r"(acc[79]),"+r"(acc[80]),"+r"(acc[81]),"+r"(acc[82]),"+r"(acc[83]),
"+r"(acc[84]),"+r"(acc[85]),"+r"(acc[86]),"+r"(acc[87]),"+r"(acc[88]),
"+r"(acc[89]),"+r"(acc[90]),"+r"(acc[91]),"+r"(acc[92]),"+r"(acc[93]),
"+r"(acc[94]),"+r"(acc[95]),"+r"(acc[96]),"+r"(acc[97]),"+r"(acc[98]),
"+r"(acc[99]),"+r"(acc[100]),"+r"(acc[101]),"+r"(acc[102]),"+r"(acc[103]),
"+r"(acc[104]),"+r"(acc[105]),"+r"(acc[106]),"+r"(acc[107]),"+r"(acc[108]),
"+r"(acc[109]),"+r"(acc[110]),"+r"(acc[111]),"+r"(acc[112]),"+r"(acc[113]),
"+r"(acc[114]),"+r"(acc[115]),"+r"(acc[116]),"+r"(acc[117]),"+r"(acc[118]),
"+r"(acc[119]),"+r"(acc[120]),"+r"(acc[121]),"+r"(acc[122]),"+r"(acc[123]),
"+r"(acc[124]),"+r"(acc[125]),"+r"(acc[126]),"+r"(acc[127])
:"l"(md_input),"l"(md_weight1):"memory");
md_input += 64 * 32 >> 4;
md_weight1 += 8 * 32 >> 4;
}
asm volatile ("wgmma.commit_group.sync.aligned;\n":::"memory");
};
for (unsigned k128id = 0; k128id < infeaturesdiv128; ++k128id) {
/* barrier synchronization code omitted */
commit_k128();
buffer_id++;
if (buffer_id == 4) buffer_id = 0;
}
const size_t ldc = gridDim.x * 512;
output += ldc * blockIdx.y * 512 + blockIdx.x * 512; //cluster_base
output += ldc * blockIdx.z * 64 + threadIdx.y * 256; // down to wg_base
output += ldc * (((threadIdx.x & 28) >> 2) + ((threadIdx.x & 96) >> 1)) +
(threadIdx.x & 3) * 2; //down to thread start
int *output2 = output + 8 * ldc;
asm volatile ("wgmma.wait_group.sync.aligned 0;\n"
:"+r"(acc[0]),"+r"(acc[1]),"+r"(acc[2]),"+r"(acc[3]),"+r"(acc[4]),
"+r"(acc[5]),"+r"(acc[6]),"+r"(acc[7]),"+r"(acc[8]),"+r"(acc[9]),
"+r"(acc[10]),"+r"(acc[11]),"+r"(acc[12]),"+r"(acc[13]),"+r"(acc[14]),
"+r"(acc[15]),"+r"(acc[16]),"+r"(acc[17]),"+r"(acc[18]),"+r"(acc[19]),
"+r"(acc[20]),"+r"(acc[21]),"+r"(acc[22]),"+r"(acc[23]),"+r"(acc[24]),
"+r"(acc[25]),"+r"(acc[26]),"+r"(acc[27]),"+r"(acc[28]),"+r"(acc[29]),
"+r"(acc[30]),"+r"(acc[31]),"+r"(acc[32]),"+r"(acc[33]),"+r"(acc[34]),
"+r"(acc[35]),"+r"(acc[36]),"+r"(acc[37]),"+r"(acc[38]),"+r"(acc[39]),
"+r"(acc[40]),"+r"(acc[41]),"+r"(acc[42]),"+r"(acc[43]),"+r"(acc[44]),
"+r"(acc[45]),"+r"(acc[46]),"+r"(acc[47]),"+r"(acc[48]),"+r"(acc[49]),
"+r"(acc[50]),"+r"(acc[51]),"+r"(acc[52]),"+r"(acc[53]),"+r"(acc[54]),
"+r"(acc[55]),"+r"(acc[56]),"+r"(acc[57]),"+r"(acc[58]),"+r"(acc[59]),
"+r"(acc[60]),"+r"(acc[61]),"+r"(acc[62]),"+r"(acc[63]),
"+r"(acc[64]),"+r"(acc[65]),"+r"(acc[66]),"+r"(acc[67]),"+r"(acc[68]),
"+r"(acc[69]),"+r"(acc[70]),"+r"(acc[71]),"+r"(acc[72]),"+r"(acc[73]),
"+r"(acc[74]),"+r"(acc[75]),"+r"(acc[76]),"+r"(acc[77]),"+r"(acc[78]),
"+r"(acc[79]),"+r"(acc[80]),"+r"(acc[81]),"+r"(acc[82]),"+r"(acc[83]),
"+r"(acc[84]),"+r"(acc[85]),"+r"(acc[86]),"+r"(acc[87]),"+r"(acc[88]),
"+r"(acc[89]),"+r"(acc[90]),"+r"(acc[91]),"+r"(acc[92]),"+r"(acc[93]),
"+r"(acc[94]),"+r"(acc[95]),"+r"(acc[96]),"+r"(acc[97]),"+r"(acc[98]),
"+r"(acc[99]),"+r"(acc[100]),"+r"(acc[101]),"+r"(acc[102]),"+r"(acc[103]),
"+r"(acc[104]),"+r"(acc[105]),"+r"(acc[106]),"+r"(acc[107]),"+r"(acc[108]),
"+r"(acc[109]),"+r"(acc[110]),"+r"(acc[111]),"+r"(acc[112]),"+r"(acc[113]),
"+r"(acc[114]),"+r"(acc[115]),"+r"(acc[116]),"+r"(acc[117]),"+r"(acc[118]),
"+r"(acc[119]),"+r"(acc[120]),"+r"(acc[121]),"+r"(acc[122]),"+r"(acc[123]),
"+r"(acc[124]),"+r"(acc[125]),"+r"(acc[126]),"+r"(acc[127])::"memory");
for (int nd8 = 0; nd8 < 32; ++nd8) {
*(int2*)output = make_int2(acc[nd8*4], acc[nd8*4+1]);
*(int2*)output2 = make_int2(acc[nd8*4+2], acc[nd8*4+3]);
output += 8;
output2 += 8;
}
} else {
/* producer code omitted */
asm volatile ("setmaxnreg.dec.sync.aligned.u32 40;\n");
}
}
This problem exists for CUDA-12.8 and CUDA-13.2 (other versions not tested).