numpy OSError:[WinError 87]使用np.vstack()时参数不正确

9q78igpj  于 2023-10-19  发布在  其他
关注(0)|答案(1)|浏览(165)

我正在尝试使用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()以上更新修复了这个问题!

hpxqektj

hpxqektj1#

您只是内存不足。这没什么奇怪的。
由于你已经打破了问题,以块的方式处理事情,这是可以修复的,通过改变你的进程,使用较小的块,限制你的内存大小,而不是CPU计数,并将结果写入磁盘-然后使用其他一些实用程序,可以将你的数据转换为可用的图像(或使用你生成的瓷砖在一个可爱的和可缩放的超级图像)。
看到-在32 K x 32 K你有正好1024兆像素-如果每个像素将采取1字节,这是1GB。但是你使用的是64位整数,所以,在主进程端,网格需要8 GB的内存,而且你的代码不需要担心任何内存节省,乍一看,它可能会使用多达4倍的内存。(主进程中的网格作为输入,然后是主进程中的块,工作进程中的每个块,以及子进程完成时返回的块)
无论如何,32 Kx32 K的图像是非常不实用的-您用来显示的任何系统都可能具有从保存为单独文件的图像创建窗口合成视图的形式,以平铺方式。你应该检查这个选项。

相关问题