numpy 使用值填充大型矩阵

axkjgtzd  于 2023-08-05  发布在  其他
关注(0)|答案(1)|浏览(83)

我有一个100 K × 12 K × 100 K的矩阵,我需要用计算结果填充它。我试着用numpy.empty创建它,但得到了一个内存错误。
所以我转向了dask。我可以创建dask数组。我正在运行一个函数,当我在for循环中遍历第0和第1维时,它创建了一个向量。然后将这个向量填充到矩阵的第i,j个位置。如果我只是按原样填充dask数组,仅赋值步骤就需要50毫秒,这对于矩阵中的所有原子单元来说都太长了。
看起来应该可以用dask的delayed函数来加速赋值,但是不能弄清楚。
以下是它在没有延迟的情况下的外观:

import dask.array as da
import dask.delayed as delayed
from dask import compute
import numpy as np

test_arr = da.empty(shape=(10000, 12, 10000), dtype='float32')
for i in range(test_arr.shape[0]):
    for j in range(test_arr.shape[1]):
        vals = np.random.normal(size=test_arr.shape[2])
        test_arr[i,j,:] = vals

字符串
下面是我使用延迟的尝试:

def populate_array(i, j, vec):
    test_arr[i, j, :] = vec
    return test_arr

for i in range(test_arr.shape[0]):
    for j in range(test_arr.shape[1]):
        vals = np.random.normal(size=test_arr.shape[2])
        delayed(populate_array)(i, j, vals)

compute(test_arr)


后者不会出错,但似乎只是返回一个全为零的数组。
我知道我也可以通过摆脱for循环和向量化来加快速度,但假设这在目前是不可行的。
我并不依赖于dask本身,但如果来自pandas / numpy,它似乎是一种具有熟悉语法的实用方法。
更新:接受的答案工作,但任务流有很多空格。我之所以提出这个问题,是因为我的实际用例中有一个复杂的create_array_chunk公式。看不到 Jmeter 板或正在发生的事情。
x1c 0d1x的数据

chhkpiq4

chhkpiq41#

我会这么做你不需要填充一个现有的Dask数组,而是一个块一个块地构建它:

import dask.array as da
import dask.delayed as delayed
import numpy as np

shape = (10000, 12, 10000)

def create_array_chunk(i, j, k):
    # should use i and j information probably here
    return np.random.normal(size=k)

i_arrays = []
for i in range(shape[0]):
    j_arrays = []
    for j in range(shape[1]):
        darray = da.from_delayed(delayed(create_array_chunk)(i, j, shape[2]), dtype=np.float64, shape=(shape[2],))
        j_arrays.append(darray)
    j_stack=da.stack(j_arrays, axis=0)
    i_arrays.append(j_stack)
j_stack = da.stack(i_arrays, axis=0)

字符串
j_stack是一个Dask Array结构,其形状为(10000,12,10000),可以看到如下:

的数据
这是一个懒惰的结构,还没有计算过任何东西。小心,如果你在上面调用compute,它会将它转换为Numpy数组,并占用大量内存。您可能希望使用to_zarr或等效工具将其流式传输到磁盘。

相关问题