我正在尝试使用CPU多处理来编码Mandelbrot集,以获得更快的速度。现在,我想渲染一个32768 x32768的图像集。在使用np.vstack()将我的文件转换为接近结尾的正确尺寸时,我遇到了一个OSError: [WinError 87] The parameter is incorrect
。
import numpy as np
import matplotlib.pyplot as plt
import multiprocessing as mp
import warnings
import time
start = time.time() #to time program
warnings.filterwarnings("ignore") #For the overflow and invalid exponent runtime warnings
b = 8192*4 #Length and Width of the 22500
if __name__ == "__main__":
num_cores = mp.cpu_count()
Y, X = np.mgrid[-1 * (b // 2):b // 2, -1 * (b // 2):b // 2] #inclue all four quadrants about (0,0), not just Quadrant I
chunk_size = b // num_cores
chunks = []
for i in range(num_cores): #create the chunks
start_row = i * chunk_size
end_row = (i + 1) * chunk_size if i < num_cores - 1 else b
chunks.append((Y, X, start_row, end_row))
pool = mp.Pool(processes=num_cores)
results = pool.imap(calculate_mandelbrot_chunk, chunks, 3) #this is the memory error for b > 2^14
pool.close()
pool.join()
####vvvvvvvvvvvvvvvvvvvvvv##################
a = np.vstack(results)
我完全傻眼了,为什么会出现这个问题。在16384 x16384或更低的时候一切都很好,但在32 k或更高的时候似乎会崩溃。我自己也不能调试这个,因为它对较小的b
值工作得很好。
更新:由于问题是我的电脑不够结实,我将采取不同的方法。下面是@jsbueno请求的代码:
import matplotlib.pyplot as plt
from mpl_interactions import ioff, panhandler, zoom_factory
import warnings
import time
warnings.filterwarnings("ignore") # For the overflow and invalid exponent runtime warnings
start = time.time() # to time program
b = 512 # Length and Width of the image
xlims = (-512,512)
ylims = (-512,512)
#(-512, 512)
#scroll code
def on_ylims_change(event_ax):
global ylims
ylims = event_ax.get_ylim()
def on_xlims_change(event_ax):
global xlims
xlims = event_ax.get_xlim()
print("Updated xlims:", xlims)
#blank(xlims, ylims)
update_plot(xlims, ylims)
#calc mandy's set
def calculate_mandelbrot(xmin, xmax, ymin, ymax, size=512):
Y, X = np.mgrid[ymin:ymax, xmin:xmax]
c = (X + Y * 1j) * (4 / size) # Complex numbers array
c = c.astype(np.complex64) # Save memory
a = np.copy(c) * 0
for k in range(64):
a = a ** 2 + c
a[a < 100] = 1 # Filter divergents out
return np.real(a) # Type casting
def update_plot(xlims, ylims):
a_zoomed = calculate_mandelbrot(xlims[0], xlims[1], ylims[0], ylims[1], size=b)
ax.imshow(a_zoomed, cmap="gray", extent=(xlims[0], xlims[1], ylims[0], ylims[1]))
def blank(xlims, ylims):
a_zoomed = np.zeros([32, 32])
ax.imshow(a_zoomed, cmap="gray", extent=(xlims[0], xlims[1], ylims[0], ylims[1]))
a = calculate_mandelbrot(xlims[0], xlims[1], ylims[0], ylims[1], size=b)
end = time.time()
print(end - start)
#### scroll wheel zoom ####
with plt.ioff():
fig, ax = plt.subplots()
ax.imshow(a, cmap="gray", extent=(-512,512,-512,512))
disconnect_zoom = zoom_factory(ax)
ax.callbacks.connect('ylim_changed', on_ylims_change)
ax.callbacks.connect('xlim_changed', on_xlims_change)
pan_handler = panhandler(fig)
plt.show()
注意:在这个b值下的每次重绘在我的电脑上只需要0.3055903911590576 seconds
。我有一个英特尔i9,所以它可能有点不同的其他人。
编辑2:添加ax.cla()
以上更新修复了这个问题!
1条答案
按热度按时间hpxqektj1#
您只是内存不足。这没什么奇怪的。
由于你已经打破了问题,以块的方式处理事情,这是可以修复的,通过改变你的进程,使用较小的块,限制你的内存大小,而不是CPU计数,并将结果写入磁盘-然后使用其他一些实用程序,可以将你的数据转换为可用的图像(或使用你生成的瓷砖在一个可爱的和可缩放的超级图像)。
看到-在32 K x 32 K你有正好1024兆像素-如果每个像素将采取1字节,这是1GB。但是你使用的是64位整数,所以,在主进程端,网格需要8 GB的内存,而且你的代码不需要担心任何内存节省,乍一看,它可能会使用多达4倍的内存。(主进程中的网格作为输入,然后是主进程中的块,工作进程中的每个块,以及子进程完成时返回的块)
无论如何,32 Kx32 K的图像是非常不实用的-您用来显示的任何系统都可能具有从保存为单独文件的图像创建窗口合成视图的形式,以平铺方式。你应该检查这个选项。