为什么 `(x / y)[i]` 比 `x[i] / y[i]` 快?

问题描述 投票:0回答:1

我是

CuPy
和 CUDA/GPU 计算的新手。有人能解释一下为什么
(x / y)[i]
x[i] / y[i]
快吗?

在利用 GPU 加速计算时,是否有任何指南可以让我快速确定哪个操作更快?避免对每个操作进行基准测试。

# In VSCode Jupyter Notebook

import cupy as cp
from cupyx.profiler import benchmark

x = cp.arange(1_000_000)
y = (cp.arange(1_000_000) + 1) / 2
i = cp.random.randint(2, size=1_000_000) == 0
x, y, i

# Output:
(array([     0,      1,      2, ..., 999997, 999998, 999999], shape=(1000000,), dtype=int32),
 array([5.000000e-01, 1.000000e+00, 1.500000e+00, ..., 4.999990e+05,
        4.999995e+05, 5.000000e+05], shape=(1000000,), dtype=float64),
 array([ True, False,  True, ...,  True, False,  True], shape=(1000000,), dtype=bool))
def test1(x, y, i):
    return (x / y)[i]

def test2(x, y, i):
    return x[i] / y[i]

print(benchmark(test1, (x, y, i)))
print(benchmark(test2, (x, y, i)))

# Output:
test1: CPU: 175.164 us +/- 61.250 (min: 125.200 / max: 765.100) us  GPU-0: 186.001 us +/- 67.314 (min: 134.144 / max: 837.568) us
test2: CPU: 342.364 us +/- 130.840 (min: 223.000 / max: 1277.600) us  GPU-0: 368.133 us +/- 136.911 (min: 225.504 / max: 1297.408) us
numpy cuda cupy
1个回答
1
投票

假设

i
数组由 50% True 和 50% false 组成。现在让我们数一下所需的所有步骤。

x[i]/y[i]
的实现中,我们必须

  • 读取整个
    i
    数组 - 1,000,000 次读取。
  • 用它来读取
    x
    y
    数组的一部分,但在 GPU 上,您无法读取单个元素。 您一次以 32 字节为单位读取内存,因此实际上,如果 True/False 分布均匀,您最终可能会读取整个
    x
    y
    数组 - 2,000,000 次读取
  • 根据
    i
  • 对 x、y 进行流压缩
  • 执行除法运算 - 500,000 次除法运算。
  • 写入结果 - 500,000 次写入

(x/y)[i]
实现中:

  • 读取整个
    i
    数组 - 1,000,000 次读取。
  • 读取整个
    x
    y
    数组 - 2,000,000 次读取
  • 执行除法运算 - 1,000,000 次除法运算。
  • 根据
    i
  • 对除法结果进行流压缩
  • 写入结果 - 500,000 次写入

唯一的区别是流压缩操作的定位和所需的除法操作的数量。 流压缩基本上是纯粹的内存绑定活动,因此区别在于访问内存的成本。 第一种方法需要两倍的流压缩。

至少在 GPU 上,触发器通常比读/写数据要便宜得多。

i
中正确/错误的百分比并不真正影响此分析。 无论比例如何,除了流压缩操作之外,两种方法都是可比的。

© www.soinside.com 2019 - 2024. All rights reserved.