为什么如果使用较小宽度的整数类型,整数数组的矢量化计算会更快?

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

我使用 NumPy 测试了不同整数宽度的整数数组上向量化算术运算的执行时间差异。我创建8位、16位、32位和64位整数数组,每个数组有1亿个随机元素,然后将每个数组乘以数字7。原因是什么(或者是什么原因,如果有的话)不止一个)与较大宽度的整数数组相比,较小宽度整数数组的计算速度更快?另外,为什么 8 位整数数组的计算速度比 16 位整数数组快约 4 倍,但 16 位整数数组的计算速度只比 32 位整数数组快约 2 倍。 32 位整数数组上的计算也仅比 64 位整数数组上的计算快约 2 倍。

这是我尝试过的代码:

import numpy as np
np.random.seed(200)
arr_int8 = np.array(np.random.randint(10, size=int(1e8)), dtype=np.int8)

np.random.seed(200)
arr_int16 = np.array(np.random.randint(10, size=int(1e8)), dtype=np.int16)

np.random.seed(200)
arr_int32 = np.array(np.random.randint(10, size=int(1e8)), dtype=np.int32)

np.random.seed(200)
arr_int64 = np.array(np.random.randint(10, size=int(1e8)), dtype=np.int64)
%%timeit
arr_int8_mult = arr_int8*7
# 28.5 ms ± 4.14 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
%%timeit
arr_int16_mult = arr_int16*7
# 124 ms ± 2.11 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
%%timeit
arr_int32_mult = arr_int32*7
# 250 ms ± 2.96 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
%%timeit
arr_int64_mult = arr_int64*7
# 533 ms ± 29.9 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

有一次(但并非总是),我在对 arr_int8_mult 进行基准测试时还收到以下消息:“最慢的运行时间比最快的运行时间长 5.97 倍。这可能意味着正在缓存中间结果。”

我不完全确定为什么从 32 位到 16 位会加速,而从 16 位到 8 位会加速更多。我最初的猜测是,可以将更多数量的较小宽度整数打包到固定宽度寄存器中(与较大宽度整数相比)。但它并不能解释为什么 8 位整数很特殊,并且具有双倍于天真的预期的 2 倍性能提升。另一个原因可能是结果被缓存,但我不确定它在实践中是如何实际发生的(如果这是真的)。性能加速大约一致为 4 倍、2 倍和 2 倍,所以必须有一个简单的解释?

python numpy vectorization simd
1个回答
0
投票

较窄的数据类型可以加快计算速度的两个原因:

  1. 数据较少。 64 位整数数组占用的 RAM 是 16 位整数数组的四倍。即使使用复杂的处理器缓存,存储和检索数据也需要时间和电量。更多的数据位数意味着更多的时间。

  2. SIMD 并行化:单指令多数据操作允许现代处理器执行多个简单操作,例如“将一堆数字乘以七”或“取两个长数字向量的内积”。这些处理器为更广泛的数据类型提供更少的并行同时操作。而且,8 位数据是一种特殊的高度优化的情况,因为它在显示操作中很重要。

numpy 在利用所有这些并行性方面做得很好。

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