为什么在双重精度阵列上执行SVD时,GPU为什么比CPU慢?

问题描述 投票:0回答:1
我在朱莉娅和python中获得相同的结果。 GPU上的单数值分解比Float64阵列的CPU慢。 (float32阵列表现如何,gpu更快。)

使用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

尽管使用GPU仅加快了几秒钟的速度,但仍然有些令人惊讶。
朱莉娅代码给出了类似的结果:

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
    ,但是我得到了相同的结果。
  1. 所有消费者级别的NVIDIA GPU对64位浮点操作的支持有限。
    尽管每个翘曲都有32个float32内核,但它只有一个float64核心。
    在我的实验中,我通常会发现float64代码运行速度慢约8倍(如果浮点操作得到了大量优化,则更多)。由于延迟问题和内存提取时间等,放缓通常不像您期望的那样32倍。
    您确实需要避免加倍。如果您确实需要额外的精度(很少见),请看“ Kahan总结”。
    
    nvidia
  2. documents在CUDA编程指南中
能力
python pytorch cuda julia svd
1个回答
1
投票




直播/循环/SM

5.0,5.2 5.3

6.0

6.16.222561284计算能力编号是指小组,8.9是Ada Lovelace(又名RTX 4000系列),8.6是Ampere(又称RTX 3000系列)等等,请参见:为了更好地性能,请查看不同的库。 ESP查看针对GPU优化的本机Cuda库(cuda usk)周围的Python包装纸。
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
最新问题
© www.soinside.com 2019 - 2025. All rights reserved.