GPU: Same results as the CPU
● Advanced4 min
The GPU gives the CPU's answers: overflow still panics with the same message, and + - * give the same bits.
gpu fn cube(n: Int32) -> Int32 {
n * n * n
}
fn main() {
const sizes: [Int32] = [10, 100, 2000]
print(sizes.map(n => cube(n)))
}The program ran, then stopped with a panic:
kavach run overflow.kav
panic: integer overflow: 4000000 * 2000 doesn't fit in Int32- Whole-number arithmetic is checked on the GPU too: overflow and division by zero panic with the CPU's message, naming the same line inside the
gpu fn. When several items fail, the GPU may report a different one first. +,-and*onFloat32give the same bits, unless the GPU fuses a multiply with an add (one rounding instead of two)./,%,**,math.powandmath.sqrtmay differ in the last bits, as GPUs are allowed to;floor,ceilandroundare exact.
When a panic shows
A map whose list stays in GPU memory doesn't wait for the GPU to finish, so a loop of them runs back to back. Here the last item overflows. On the CPU the panic stops the loop; on the GPU, looped prints first:
gpu fn square(n: Int32) -> Int32 {
n * n
}
fn main() {
let ns: [Int32] = []
for i in 0..1000 {
ns.push(Int32(i % 7))
}
ns.push(100000)
for _ in 0..3 {
ns = ns.map(square)
}
print("looped")
print(ns[0])
}KAVACH_GPU=off kavach run --native src/main.kav
panic: integer overflow: 100000 * 100000 doesn't fit in Int32 at src/main.kav:2
KAVACH_GPU=on kavach run --native src/main.kav
looped panic: integer overflow: 100000 * 100000 doesn't fit in Int32 at src/main.kav:2
- The panic shows the next time the program reads the list on the CPU (
ns[0]here), when another GPU call waits for its own result, or when the program ends. - Its message and line are the same either way. Only when it shows changes: code after the
mapmay have run by then. - To find where a panic starts, run with
KAVACH_GPU=off.