我的代码中速度瓶颈是在一个双重循环中,遍历两个数组x和y的元素。提高性能的标准HPC技巧是对循环进行分块,以最小化缓存未命中。我试图使用Python生成器来进行分块,但需要在外层for循环中不断重新创建已用过的生成器,这会降低我的运行时间。
问题:
是否有更智能的算法来构建适当的生成器,以执行分块双重循环?
具体说明:
我将创建两个虚拟数组x和y,为了说明简单,我将它们保持较短,但实际上这些是具有约1e6个元素的numpy数组。
现在让我们使用生成器以块的形式执行此循环:
请注意,为了解决这个问题并实现生成器方案,我必须在外层循环中不断重新创建ychunk_gen。由于y是一个大数组,这会导致我的运行时间变慢(对于约1e6个元素,在我的笔记本电脑上创建此生成器需要约20毫秒)。
有没有更聪明的方式来构建生成器,以避免这个问题?或者放弃使用生成器方案是必要的吗?
(注:在实践中,我正在使用Cython执行这个紧密的循环,但以上所有内容都适用)。
问题:
是否有更智能的算法来构建适当的生成器,以执行分块双重循环?
具体说明:
我将创建两个虚拟数组x和y,为了说明简单,我将它们保持较短,但实际上这些是具有约1e6个元素的numpy数组。
x = np.array(['a', 'b', 'b', 'c', 'c', 'd'])
y = np.array(['e', 'f', 'f', 'g'])
朴素的双重循环代码如下:
for xletter in x:
for yletter in y:
# algebraic manipulations on x & y
现在让我们使用生成器以块的形式执行此循环:
chunk_size = 3
xchunk_gen = (x[i: i+chunk_size] for i in range(0, len(x), chunk_size))
for xchunk in xchunk_gen:
ychunk_gen = (y[i: i+chunk_size] for i in range(0, len(y), chunk_size))
for ychunk in ychunk_gen:
for xletter in xchunk:
for yletter in ychunk:
# algebraic manipulations on x & y
请注意,为了解决这个问题并实现生成器方案,我必须在外层循环中不断重新创建ychunk_gen。由于y是一个大数组,这会导致我的运行时间变慢(对于约1e6个元素,在我的笔记本电脑上创建此生成器需要约20毫秒)。
有没有更聪明的方式来构建生成器,以避免这个问题?或者放弃使用生成器方案是必要的吗?
(注:在实践中,我正在使用Cython执行这个紧密的循环,但以上所有内容都适用)。
x
和y
是RAM中的列表,那么像你这样使用生成器并没有任何好处......另外,你可以直接运行counter = len(x) * len(y)
。 - Jörn Hees