我正在尝试使用模块perlin-noise创建一个FBM纹理,但是它需要很长时间才能执行。我已经实现了multiprocessing,结果发现这个程序仍然运行在单个内核上。我尝试过寻找其他有相同问题的人,但是大多数线程都是7+年的并且/或涉及到与不同操作系统相关的问题和解决方案。
我的操作系统是Windows8.1,我有一个四核CPU,运行Python3.9.2
以下是节目:
from perlin_noise import PerlinNoise
from multiprocessing import Pool
def world(n):
noise1 = PerlinNoise(octaves=3, seed=1)
noise2 = PerlinNoise(octaves=6, seed=1)
noise3 = PerlinNoise(octaves=12, seed=1)
noise4 = PerlinNoise(octaves=24, seed=1)
noise5 = PerlinNoise(octaves=48, seed=1)
world = []
for i in range(n):
row = []
for j in range(n):
noise_val = noise1([i/n, j/n])
noise_val += 0.5 * noise2([i/n, j/n])
noise_val += 0.25 * noise3([i/n, j/n])
noise_val += 0.125 * noise4([i/n, j/n])
noise_val += 0.0625 * noise5([i/n, j/n])
row.append(noise_val)
world.append(row)
def main():
start = time.time()
nums = [128]
p = Pool()
p.map(world, nums)
p.close()
p.join()
end = time.time()
print(end - start)
if __name__ == '__main__':
import time
from distributed import Client
client = Client()
main()那么,怎么回事?我是否犯了错误,认为多处理可以在这些for-循环上工作?
谢谢!
发布于 2021-05-27 10:24:25
它只使用一个进程的原因很简单。在Pool.map中,您只传递了一个长度的列表.
Pool(n).map(function, iterable)所做的是将提供的功能应用于提供的iterable的每个元素(在本例中,是list),并使用工作进程的n数。
由于nums中只有128个任务,所以它只创建一个任务,因此从未使用过其他进程。
正确的用法如下所示:
from multiprocessing import pool
def work(val):
return hash(val ** 10000000)
if __name__ == '__main__':
p = pool.Pool(8)
with p:
output = p.map(work, [i for i in range(1, 31)])
print(output)这个例子将有8个进程,因此利用8个逻辑核心。由于我们给出了从1到30的数字,p.map将使用8个进程将函数work应用于这些数字中的每一个,因此它可以同时运行8个函数。
当我们运行它时,我们可以看到它的效果。

当然,它使用了更多的进程来在进程之间进行交流,等等--我承认我不知道其中的潜在细节。
附带注意,为了使你的工作更有效率,你应该尽量克制自己。
检查这个简单的例子,附加大量的时间和测量它所花费的时间。
>>> import timeit
>>> def appending():
... output = []
... for i in range(1000000):
... output.append(i)
... return output
...
>>> def list_comp():
... return [i for i in range(1000000)]
>>> print(f"{timeit.timeit(appending, number=100):.2}")
8.1
>>> print(f"{timeit.timeit(list_comp, number=100):.2}")
5.2正如您所看到的,附加比列表理解慢得多--但这并不意味着不使用list.append --只是不要过度使用它。
https://stackoverflow.com/questions/67719075
复制相似问题