GPU上JAX批量矩阵乘法:大矩阵为何性能更优?
JAX GPU批量矩阵乘法的异常性能差异问题
在GPU上使用JAX执行批量矩阵乘法时,发现计算形状为(1000, 1000, 3, 35) @ (1000, 1000, 35, 1)的矩阵乘法时,f64 dtype下速度比(1000, 1000, 3, 25) @ (1000, 1000, 25, 1)快约3倍,f32 dtype下快约5倍。但CPU上JAX和NumPy均无此表现,GPU上CuPy也不存在该差异。
使用环境:
- JAX 0.4.32
- GPU:NVIDIA RTX A5000(Tesla T4上结果类似)
基础导入与初始化代码
import numpy as np import cupy as cp from cupyx.profiler import benchmark from jax import config config.update("jax_enable_x64", True) import jax import jax.numpy as jnp import matplotlib.pyplot as plt rng = np.random.default_rng() x = np.arange(5, 55, 5)
GPU计时代码
dtype = cp.float64 timings_cp = [] for i in range(5, 55, 5): a = cp.array(rng.random((1000, 1000, 3, i)), dtype=dtype) b = cp.array(rng.random((1000, 1000, i, 1)), dtype=dtype) timings_cp.append(benchmark(lambda a, b: a@b, (a, b), n_repeat=10, n_warmup=10)) dtype = jnp.float64 timings_jax_gpu = [] with jax.default_device(jax.devices('gpu')[0]): for i in range(5, 55, 5): a = jnp.array(rng.random((1000, 1000, 3, i)), dtype=dtype) b = jnp.array(rng.random((1000, 1000, i, 1)), dtype=dtype) func = jax.jit(lambda a, b: a@b) timings_jax_gpu.append(benchmark(lambda a, b: func(a, b).block_until_ready(), (a, b), n_repeat=10, n_warmup=10)) plt.figure() plt.plot(x, [i.gpu_times.mean() for i in timings_cp], label="CuPy") plt.plot(x, [i.gpu_times.mean() for i in timings_jax_gpu], label="JAX GPU") plt.legend()
特定形状计时代码
dtype = jnp.float64 with jax.default_device(jax.devices('gpu')[0]): a = jnp.array(rng.random((1000, 1000, 3, 25)), dtype=dtype) b = jnp.array(rng.random((1000, 1000, 25, 1)), dtype=dtype) func = jax.jit(lambda a, b: a@b) print(benchmark(lambda a, b: func(a, b).block_until_ready(), (a, b), n_repeat=1000, n_warmup=10).gpu_times.mean()) a = jnp.array(rng.random((1000, 1000, 3, 35)), dtype=dtype) b = jnp.array(rng.random((1000, 1000, 35, 1)), dtype=dtype) print(benchmark(lambda a, b: func(a, b).block_until_ready(), (a, b), n_repeat=1000, n_warmup=10).gpu_times.mean())
计时结果
f64:
0.01453789699935913
0.004859122595310211f32:
0.005860503035545349
0.001209742688536644
CPU计时代码
timings_np = [] for i in range(5, 55, 5): a = rng.random((1000, 1000, 3, i)) b = rng.random((1000, 1000, i, 1)) timings_np.append(benchmark(lambda a, b: a@b, (a, b), n_repeat=10, n_warmup=10)) timings_jax_cpu = [] with jax.default_device(jax.devices('cpu')[0]): for i in range(5, 55, 5): a = jnp.array(rng.random((1000, 1000, 3, i))) b = jnp.array(rng.random((1000, 1000, i, 1))) func = jax.jit(lambda a, b: a@b) timings_jax_cpu.append(benchmark(lambda a, b: func(a, b).block_until_ready(), (a, b), n_repeat=10, n_warmup=10)) plt.figure() plt.plot(x, [i.cpu_times.mean() for i in timings_np], label="NumPy") plt.plot(x, [i.cpu_times.mean() for i in timings_jax_cpu], label="JAX CPU") plt.legend()
相关性能可视化图表见原文。
请问该性能差异的原因是什么?
内容的提问来源于stack exchange,提问作者Nin17
相关产品推荐
相关产品推荐

