下面的代码工作2-3秒。让x5-10+更快是真的吗?我试着做泊松鞋带,但效果更慢。此外,由于我在更高级别的代码中具有并行化,所以无法使用joblib和多处理特性。
lst = range(1000000)
result = np.random.choice(lst, size=(100, len(lst)), replace=True).mean(axis=1)我认为主要的问题是np.random.choice的重组,也许它可以用于优化。
发布于 2021-12-09 01:17:26
TL;DR: np.random.choice是经济放缓的主要原因。问题是,在这种情况下,Numpy使用延迟限制的算法,这很难在顺序上做得更好(由于随机访问内存模式)。随机数生成也相当昂贵。
实际上,必须从内存中获取输入列表中的随机索引项。由于输入列表由Numpy转换为连续的4到8 MiB,因此输入数组可能不适合您的CPU缓存。因此,从主RAM中获取值。此外,随机访问模式阻止处理器快速地从RAM加载值。现代主流x86处理器内核可以同时获取大约10个项(这是令人惊讶的,因为代码应该是顺序的)。然而,当前(DDR) RAMs的延迟是about 50-100 ns。因此,获取RAM应该花费大约一秒的1亿个随机项。此外,还必须生成1亿个随机值(相当慢),还必须填充400~800个MiB中间缓冲区。
加快这种延迟限制计算的一个简单方法是使用多线程。您可以使用Numba (或Cython)来实现这一点。此外,可以使用较小的临时数组来减少使用大型Numpy数组的开销。这些方法可以实时计算.
import numba as nb
# Assume the input array is contiguous
@nb.njit('float64[:](int_[::1])', parallel=True)
def parallelShuffle(arr):
n, m = 100, arr.size
res = np.empty(n, np.float64)
for i in nb.prange(n):
s = 0.0
tmp = np.random.randint(0, m, m)
for j in range(m):
s += lst[tmp[j]]
res[i] = s / m
return res
lst = range(1000000)
lst = np.fromiter(lst, dtype=np.int_) # Fast iterable to Numpy conversion
result = parallelShuffle(lst)在我的6核计算机上,这个实现比快4.5倍。注意,基于整数的Numba随机数生成器目前比Numpy慢得可怜。
发布于 2021-12-09 04:03:37
如果不将python range对象转换为numpy数组并从中进行选择,则可以获得~3x提升:
result = np.random.choice(1000000, size=(100, 1000000), replace=True).mean(axis=1)以这种方式选择一组数字与生成相同范围内的数字是完全相同的。不幸的是,这两种方法花费的时间相同:
result = np.random.randint(1000000, size=(100, 1000000)).mean(axis=1)https://stackoverflow.com/questions/70282665
复制相似问题