使用Pytorch的Pypython基准代码:
import time
import torch
from torch.linalg import svd
f64 = torch.double
f32 = torch.float
cpu = torch.device("cpu")
gpu = torch.device("cuda")
# X = torch.rand(5_000, 10_000, dtype=f32)
X = torch.rand(5_000, 10_000, dtype=f64)
X_cpu = X.to(cpu)
X_gpu = X.to(gpu)
print(X_cpu.type())
# Warmup
U, Sig, Vt = svd(X_cpu, full_matrices = True)
# Timed run (CPU)
t1 = time.perf_counter()
U, Sig, Vt = svd(X_cpu, full_matrices = True)
t2 = time.perf_counter()
print(U.type())
print(X_cpu.type())
# Warmup
U, Sig, Vt = svd(X_gpu, full_matrices = True)
# Timed run (GPU)
t3 = time.perf_counter()
U, Sig, Vt = svd(X_gpu, full_matrices = True)
t4 = time.perf_counter()
print(U.type())
print(f"Time CPU (s): {t2-t1}")
print(f"Time GPU (s): {t4-t3}")
对于上述float64阵列,我得到:
Time CPU (s): 14.52491476599971
Time GPU (s): 56.79755901500175
如果我使用float32阵列,我会得到更合理的外观:
Time CPU (s): 9.301500292000128
Time GPU (s): 6.969021153003268
朱莉娅代码给出了类似的结果:
using LinearAlgebra
using Flux
using CUDA
using cuDNN
X = rand(5_000, 10_000)
println("typeof(X): $(typeof(X))")
# Warmup
U, Sig, V = LinearAlgebra.svd(X)
# Timed run
t1 = time_ns()
U, Sig, V = LinearAlgebra.svd(X)
t2 = time_ns()
println("typeof(U): $(typeof(U))")
X_gpu = X |> gpu |> f64
println("typeof(X_gpu): $(typeof(X_gpu))")
# Warmup
U, Sig, V = CUDA.svd!(X_gpu)
# Timed run
t3 = time_ns()
U, Sig, V = CUDA.svd!(X_gpu)
t4 = time_ns()
println("typeof(U): $(typeof(U))")
println("Time CPU (s): $((t2-t1)/1e9)")
println("Time GPU (s): $((t4-t3)/1e9)")
对于此float64数组,GPU再次比CPU更长:
Time CPU (s): 28.641290506
Time GPU (s): 57.069009417
,但是,切换到float32再次产生合理的结果:
Time CPU (s): 15.096364932
Time GPU (s): 7.283513658
两个问题:
为什么float64阵列在GPU上运行较差?如果相关,我正在使用NVIDIA 40系列GPU。有任何方法可以改善GPU上SVD运行的性能吗? (尤其是对于Float64阵列,但是为Float32阵列加速SVD也很不错。)一种可能的方法是改变执行SVD的方式。我检查了一下,似乎没有任何可选参数可用于cuda.jl的SVD函数。我尝试为Pytorch的SVD功能设置
full_matrices=False
所有消费者级别的NVIDIA GPU对64位浮点操作的支持有限。 尽管每个翘曲都有32个float32内核,但它只有一个float64核心。 在我的实验中,我通常会发现float64代码运行速度慢约8倍(如果浮点操作得到了大量优化,则更多)。由于延迟问题和内存提取时间等,放缓通常不像您期望的那样32倍。 您确实需要避免加倍。如果您确实需要额外的精度(很少见),请看“ Kahan总结”。nvidia
直播/循环/SM
6.0
7.x | 8.0 | 8.6 | 8.9 | 9.0 | 16位浮点 | n/a | 256 | 128 | ||
---|---|---|---|---|---|---|---|---|---|---|
128 | 256 | 256 | 128 | 256 | 32位浮点 | 128 | 128 | 64 | 128 | |
64 | 64 | 128 | 128 | 128 | 64位浮点 | 4 | 4 | 32 | 4 | |
32 | 32 | 2 | 2 | 64 | 注意在所有非服务器硬件上如何严重限制吞吐量。这限制了支持很少使用的64位操作所需的芯片房地产量,这使NVIDIA可以使用较小且更便宜的模具使消费者GPU(或者花更多地花费更多的硅来优化32位性能)。 | Https:// en.wikipedia.org/wikipedia.org/wikipedia.org/wiki/cuda/cuda/cuda/cuda/cuda |