So why do you think it’s slow?
Some observations regarding outputlayer_cuda_input_backward_kernel:

I usually read the upper bounds of my for loops into a local variable. (I’m never sure whether it would be strictly necessary, but you want that to be cached in a register.)
If the k loop is large, you can parallelize the reduction by partially reducing within a thread and then across threads. This is a somewhat common pattern, I’m trying to describe it in my sinkhorn kernel blog post 7.
In the for loop assigning weight[col] to a local (auto weight_col = weight[col]) might reduce some indexing.

Moving to outputlayer_cuda_weight_backward_kernel:

I would cache the indices grad_indexs[1][col] as it is constant in the for loop, for the input, you might also cache the partially indexed accessor (like above).
For grad_weight[k][grad_indexs[1][col]] += you need to be sure that no two threads will try to write to the same memory location for this to even be correct. If not, this is where the dreaded (for determinism and performance unless accesses are sparse) indexAdd comes into play. You would need to do some relatively elaborate scanning f that doesn’t work.

Similar considerations around the += apply to the bias backward.
I haven’t really looked at the thread/grid layout. You likely want to benchmark things as you try the above for potential improvements.
Best regards
Thomas