创建和填充巨大的numpy 2D数组的最快方法是什么?

6

我需要创建并填充一个巨大的数组(例如96GB,72000行*72000列),其中每个元素都来自于数学公式。该数组将在计算后生成。

import itertools, operator, time, copy, os, sys
import numpy 
from multiprocessing import Pool


def f2(x):  # more complex mathematical formulas that change according to values in *i* and *x*
    temp=[]
    for i in combine:
        temp.append(0.2*x[1]*i[1]/64.23)
    return temp

def combinations_with_replacement_counts(n, r):  #provide all combinations of r balls in n boxes
   size = n + r - 1
   for indices in itertools.combinations(range(size), n-1):
       starts = [0] + [index+1 for index in indices]
       stops = indices + (size,)
       yield tuple(map(operator.sub, stops, starts))

global combine
combine = list(combinations_with_replacement_counts(3, 60))  #here putted 60 but need 350 instead
print len(combine)
if __name__ == '__main__':
    t1=time.time()
    pool = Pool()              # start worker processes
    results = [pool.apply_async(f2, (x,)) for x in combine]
    roots = [r.get() for r in results]
    print roots [0:3]
    pool.close()
    pool.join()
    print time.time()-t1
  • 如何快速创建和填充大型numpy数组?先填充列表,然后聚合再转换成numpy数组是最快的方法吗?
  • 如果2d数组的行、列和案例之间相互独立,可以并行计算以加速数组的填充吗?使用多进程优化此类计算的线索/路径有哪些?

需要实时处理还是可以离线计算并使用例如pickle进行读取? - Fredrik Pihl
我更喜欢实时,但如果选用pickling更快,我也不介意...希望我对你的问题理解得很好? - sol
2个回答

1
我知道你可以创建共享的numpy数组,可以从不同的线程中更改(假设更改的区域不重叠)。以下是可以用来实现此操作的代码草图(我在stack overflow的某个地方看到了原始想法,编辑:这里是https://dev59.com/T2035IYBdhLWcg3wNtVw#5550156)。
import multiprocessing as mp ,numpy as np, ctypes

def shared_zeros(n1, n2):
    # create a 2D numpy array which can be then changed in different threads
    shared_array_base = mp.Array(ctypes.c_double, n1 * n2)
    shared_array = np.ctypeslib.as_array(shared_array_base.get_obj())
    shared_array = shared_array.reshape(n1, n2)
    return shared_array

class singleton:
    arr = None

def dosomething(i):
    # do something with singleton.arr
    singleton.arr[i,:] = i
    return i

def main():
    singleton.arr=shared_zeros(1000,1000)
    pool = mp.Pool(16)
    pool.map(dosomething, range(1000))

if __name__=='__main__':
    main()

它能工作吗?我不明白单例类的好处/技巧。我遇到了TypeError:'NoneType'对象不支持项目赋值。我尝试过修改,但没有结果。你能再帮我一点吗? - sol
我的代码在Linux上可以正常工作(已验证)。如果你使用的是Windows,那么恐怕你需要采取不同的方法(因为singleton.arr值不会被进程池中的进程继承)。 - sega_sai

0
你可以使用所需形状创建一个空的 numpy.memmap 数组,然后使用 multiprocessing.Pool 来填充其值。正确地执行此操作还将保持池中每个进程的内存占用相对较小。

请参考https://dev59.com/t2kw5IYBdhLWcg3wVpFi,我认为这不起作用。 - sega_sai
@sega_sai 很有趣。我不会删除我的回答,因为我相信其他人可以像我一样从看到它以及你的评论来了解它。谢谢。 - shx2

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接