numpy相关系数:导致seg故障的大型阵列上的np.点(A,A.T)

numpy相关系数:导致seg故障的大型阵列上的np.点(A,A.T),numpy,blas,dot-product,Numpy,Blas,Dot Product,注: 我有一个大数组a: Speed is not as important as getting a final result. However, some speed up over worst case is required as well. 我需要计算相关系数 A.shape=(20000,265) # or possibly larger like 50,000 x 265 我只是借用了他们的代码,编写了我自己的cov/corr,而不是转换成双精度,因为我真的只需要32位浮点。

注:

我有一个大数组a:

Speed is not as important as getting a final result.
However, some speed up over worst case is required as well. 
我需要计算相关系数

A.shape=(20000,265) # or possibly larger like 50,000 x 265
我只是借用了他们的代码,编写了我自己的cov/corr,而不是转换成双精度,因为我真的只需要32位浮点。我抛弃了conj(),因为我的数据总是真实的

np.corrcoeff # internally casts the results as doubles
我的内存仍然不足,我使用的是一台大内存机器,264GB

有人告诉我,FastC库可能正在使用一个打破常规的例程 将产品点成几块,为了优化这一点,元素的数量被填充为2的幂

我真的不需要计算相关系数矩阵的对称部分。 但是,我看不到一种方法可以在合理的时间内通过python循环“手动”完成这项工作

有人知道有什么方法可以让numpy获得一个像样的点积例程,它可以平衡内存使用和速度

干杯

更新:

有趣的是,写这些问题往往能帮助我找到更好的谷歌查询语言

我们发现:

cov = A.dot(A.T)/n  #where A is an array of 32 bit floats
diag = np.diag(cov)
corr = cov / np.sqrt(np.mutliply.outer(d,d))
我不确定我是否遵守……因此,请评论或提供有关此解决方案的答案,您自己的想法,或只是对这类问题的一般评论

短暂性脑缺血发作

编辑:我很抱歉,因为我的数组比我想象的要大得多。 数组大小实际上是151000 x 265 我在一台264 GB的计算机上内存不足,至少有230 GB的可用空间

我很惊讶numpy调用blas dgemm并小心使用C顺序数组
没有做下蹲。

您可以试试看
np.einsum
是否比dot更适合您的情况:

http://wiki.scipy.org/PerformanceTips

dot
的内部工作机制有点模糊,因为它试图使用BLAS优化例程,这有时要求数组的副本以Fortran顺序排列,不确定这里是否是这种情况
einsum将缓冲其输入,并在可能的情况下使用矢量化SIMD操作,但除此之外,它基本上将运行朴素的三个嵌套循环来计算矩阵积。

使用英特尔mkl编译的Python将在大约30秒内以12GB内存运行:

cov = np.einsum('ij,kj->ik', A, A) / n
如果您无法访问intel的MKL,请下载python并安装accelerate软件包,该软件包具有30天的试用版,或免费提供给学术界,其中包含MKL编译。各种其他C++ BLAS库也应该工作——即使它从C到F复制数组,也不应该占用更多的内存。 我能想到的唯一一件事是,您的安装正在尝试做的是尝试将整个50000 x 50000 x 265阵列保存在内存中,坦白说,这非常糟糕。作为参考,32 50000 x 50000阵列仅为10GB,而上述阵列为2.6TB

如果是gemm问题,您可以尝试块gemm公式:

>>> A = np.random.rand(50000,265).astype(np.float32)
>>> A.dot(A.T)
array([[ 86.54410553,  64.25226593,  67.24698639, ...,  68.5118103 ,
         64.57299805,  66.69223785],
         ...,
       [ 66.69223785,  62.01016235,  67.35866547, ...,  66.66306305,
         65.75863647,  86.3017807 ]], dtype=float32)

这会更慢,但有望克服内存问题。

更新:经过仔细检查,dot产品完成时没有出现错误 输出数组由151000列中95000列到末尾的零组成。 也就是说,对于所有行,out[:,94999]=非零,但out[:,95000]=0

这太烦人了

交换,提到了一些我也想过的东西…因为blas是fortran,不应该 输入的顺序是F顺序。。。?其中,如下面的scipy doc页面所示,为C订单

尝试F顺序导致分段错误。我又回到原点了

原职 我终于找到了我的问题,和往常一样在细节上

我使用的是一个np.float32数组,它存储为F顺序。据我所知,我无法控制F顺序,因为数据是使用图像库从图像加载的

def chunk_gemm(A, B, csize):
    out = np.empty((A.shape[0],B.shape[1]), dtype=A.dtype)
    for i in xrange(0, A.shape[0], csize):
        iend = i+csize
        for j in xrange(0, B.shape[1], csize):
            jend = j+csize
            out[i:iend, j:jend] = np.dot(A[i:iend], B[:,j:jend])
    return out
这个3级blas程序就完成了。我的问题有两方面:

import scipy
roi = np.ascontiguousarray( roi )# see roi.flags below
out = scipy.linalg.blas.sgemm(alpha=1.0, a=roi, b=roi, trans_b=True)
而且。。。我用的是blas dgemm而不是sgemm。d代表double,s代表single。 请参阅此pdf:

我看了一眼就不知所措了……我回去读了维基百科关于blas例程的文章,以了解3级与其他级别的对比:

现在它在A=150000 x 265上工作,执行:

roi.flags
C_CONTIGUOUS : False
F_CONTIGUOUS : True
OWNDATA : True
WRITEABLE : True
ALIGNED : True
UPDATEIFCOPY : False

谢谢大家的想法…知道这是可以做到的是最重要的

谢谢Jaime,在我使用最新的研究进行测试后,我会试试你的想法。如果它能节省内存并避免seg故障,那么它就是一个解决方案。希望我也能找到一个速度相当快的解决方案…einsum看起来像预期的那样工作…缓慢但合理的内存使用。我学过物理,非常喜欢这个符号。你的numpy链接到哪个blas库
np.\uuuu config\uuuu.blas\u opt\u info
@jtaylor我已经读了一些关于这个配置bf的内容,但对这个输出的含义不太自信:{'define\u macros':[('ATLAS\u info','“\\\'3.8.4\\”)],'language':'c','libraries':['ptf77blas','ptcblas ATLAS'],“我在一台有264 GB的机器上内存不足,至少有230 GB可用空间”看起来很可疑,您使用的是什么操作系统和python\numpy的哪个版本?(我是指x32或x64?)很高兴知道…将投入更多精力让MKL工作,并希望重复您的结果。THX!结果证明MKL不是我工作场所可以使用的解决方案。如果您注意到我最近的编辑,数组大小要大得多。如果您想用更大的数组再次运行sim卡,我很好奇您的结果。干杯我不明白您的注释
numpy.dot
正确地选择了正确的BLAS例程
DGEMM
SGEMM
CGEMV
,或者其他任何程序。如果您有很多零,可以使用稀疏矩阵
A \dot A.T