This looks like a lot of calcs for the inner loop but is quite easily optimized. The compiler knows that (j * ni + i) is constant in the k loop and that ni * nj is constant. Check the assembly output. But it is probably better to reorder the loops and traverse linearly through memory so that each cache line brought down is fully consumed in order.