- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我有一个 scipy.sparse.csr_matrix 格式的大稀疏矩阵 X,我想利用并行性将其乘以一个 numpy 数组 W。经过一些研究,我发现我需要在多处理中使用 Array 以避免在进程之间复制 X 和 W(来自例如:How to combine Pool.map with Array (shared memory) in Python multiprocessing? 和 Is shared readonly data copied to different processes for Python multiprocessing?)。这是我最近的尝试
import multiprocessing
import numpy
import scipy.sparse
import time
def initProcess(data, indices, indptr, shape, Warr, Wshp):
global XData
global XIndices
global XIntptr
global Xshape
XData = data
XIndices = indices
XIntptr = indptr
Xshape = shape
global WArray
global WShape
WArray = Warr
WShape = Wshp
def dot2(args):
rowInds, i = args
global XData
global XIndices
global XIntptr
global Xshape
data = numpy.frombuffer(XData, dtype=numpy.float)
indices = numpy.frombuffer(XIndices, dtype=numpy.int32)
indptr = numpy.frombuffer(XIntptr, dtype=numpy.int32)
Xr = scipy.sparse.csr_matrix((data, indices, indptr), shape=Xshape)
global WArray
global WShape
W = numpy.frombuffer(WArray, dtype=numpy.float).reshape(WShape)
return Xr[rowInds[i]:rowInds[i+1], :].dot(W)
def getMatmat(X):
numJobs = multiprocessing.cpu_count()
rowInds = numpy.array(numpy.linspace(0, X.shape[0], numJobs+1), numpy.int)
#Store the data in X as RawArray objects so we can share it amoung processes
XData = multiprocessing.RawArray("d", X.data)
XIndices = multiprocessing.RawArray("i", X.indices)
XIndptr = multiprocessing.RawArray("i", X.indptr)
def matmat(W):
WArray = multiprocessing.RawArray("d", W.flatten())
pool = multiprocessing.Pool(processes=multiprocessing.cpu_count(), initializer=initProcess, initargs=(XData, XIndices, XIndptr, X.shape, WArray, W.shape))
params = []
for i in range(numJobs):
params.append((rowInds, i))
iterator = pool.map(dot2, params)
P = numpy.zeros((X.shape[0], W.shape[1]))
for i in range(numJobs):
P[rowInds[i]:rowInds[i+1], :] = iterator[i]
return P
return matmat
if __name__ == '__main__':
#Create a random sparse matrix X and a random dense one W
X = scipy.sparse.rand(10000, 8000, 0.1)
X = X.tocsr()
W = numpy.random.rand(8000, 20)
startTime = time.time()
A = getMatmat(X)(W)
parallelTime = time.time()-startTime
startTime = time.time()
B = X.dot(W)
nonParallelTime = time.time()-startTime
print(parallelTime, nonParallelTime)
但是输出类似于:(4.431, 0.165) 表明并行版本比非并行乘法慢得多。
我相信在将大数据复制到进程时类似的情况下可能会导致减速,但这里不是这种情况,因为我使用 Array 来存储共享变量(除非它发生在 numpy.frombuffer 中或创建时一个 csr_matrix,但后来我找不到直接共享 csr_matrix 的方法)。速度慢的另一个可能原因是为每个进程返回每个矩阵乘法的大结果但是我不确定解决这个问题的方法。
有人能看出我哪里错了吗?谢谢你的帮助!
更新:我不能确定,但我认为在进程之间共享大量数据并不是那么有效,理想情况下我应该使用多线程(尽管全局解释器锁 (GIL) 使这变得非常困难)。解决此问题的一种方法是使用 Cython 发布 GIL(请参阅 http://docs.cython.org/src/userguide/parallelism.html ),尽管许多 numpy 函数需要通过 GIL。
最佳答案
最好的选择是使用 Cython 降到 C。这样你就可以击败 GIL 并使用 OpenMP。我对多处理速度变慢并不感到惊讶——那里有很多开销。
这是 CSparse 稀疏矩阵的简单包装器 OpenMP 包装器 - python 中的矢量乘积代码。
在我的笔记本电脑上,它的运行速度比 scipy 快一点。但是我没有那么多核心。代码,包括 setup.py 脚本和 C 头文件和东西在这个要点中:https://gist.github.com/rmcgibbo/6019670
我怀疑如果你真的希望并行代码很快(在我的笔记本电脑上,它只比单线程 scipy 快 20%,即使使用 4 个线程),你需要更仔细地考虑并行性在哪里发生的事情比我做的要多,注意缓存位置。
# psparse.pyx
#-----------------------------------------------------------------------------
# Imports
#-----------------------------------------------------------------------------
cimport cython
cimport numpy as np
import numpy as np
import scipy.sparse
from libc.stddef cimport ptrdiff_t
from cython.parallel import parallel, prange
#-----------------------------------------------------------------------------
# Headers
#-----------------------------------------------------------------------------
ctypedef int csi
ctypedef struct cs:
# matrix in compressed-column or triplet form
csi nzmax # maximum number of entries
csi m # number of rows
csi n # number of columns
csi *p # column pointers (size n+1) or col indices (size nzmax)
csi *i # row indices, size nzmax
double *x # numerical values, size nzmax
csi nz # # of entries in triplet matrix, -1 for compressed-col
cdef extern csi cs_gaxpy (cs *A, double *x, double *y) nogil
cdef extern csi cs_print (cs *A, csi brief) nogil
assert sizeof(csi) == 4
#-----------------------------------------------------------------------------
# Functions
#-----------------------------------------------------------------------------
@cython.boundscheck(False)
def pmultiply(X not None, np.ndarray[ndim=2, mode='fortran', dtype=np.float64_t] W not None):
"""Multiply a sparse CSC matrix by a dense matrix
Parameters
----------
X : scipy.sparse.csc_matrix
A sparse matrix, of size N x M
W : np.ndarray[dtype=float564, ndim=2, mode='fortran']
A dense matrix, of size M x P. Note, W must be contiguous and in
fortran (column-major) order. You can ensure this using
numpy's `asfortranarray` function.
Returns
-------
A : np.ndarray[dtype=float64, ndim=2, mode='fortran']
A dense matrix, of size N x P, the result of multiplying X by W.
Notes
-----
This function is parallelized over the columns of W using OpenMP. You
can control the number of threads at runtime using the OMP_NUM_THREADS
environment variable. The internal sparse matrix code is from CSPARSE,
a Concise Sparse matrix package. Copyright (c) 2006, Timothy A. Davis.
http://www.cise.ufl.edu/research/sparse/CSparse, licensed under the
GNU LGPL v2.1+.
References
----------
.. [1] Davis, Timothy A., "Direct Methods for Sparse Linear Systems
(Fundamentals of Algorithms 2)," SIAM Press, 2006. ISBN: 0898716136
"""
if X.shape[1] != W.shape[0]:
raise ValueError('matrices are not aligned')
cdef int i
cdef cs csX
cdef np.ndarray[double, ndim=2, mode='fortran'] result
cdef np.ndarray[csi, ndim=1, mode = 'c'] indptr = X.indptr
cdef np.ndarray[csi, ndim=1, mode = 'c'] indices = X.indices
cdef np.ndarray[double, ndim=1, mode = 'c'] data = X.data
# Pack the scipy data into the CSparse struct. This is just copying some
# pointers.
csX.nzmax = X.data.shape[0]
csX.m = X.shape[0]
csX.n = X.shape[1]
csX.p = &indptr[0]
csX.i = &indices[0]
csX.x = &data[0]
csX.nz = -1 # to indicate CSC format
result = np.zeros((X.shape[0], W.shape[1]), order='F', dtype=np.double)
for i in prange(W.shape[1], nogil=True):
# X is in fortran format, so we can get quick access to each of its
# columns
cs_gaxpy(&csX, &W[0, i], &result[0, i])
return result
它从 CSparse 调用一些 C。
// src/cs_gaxpy.c
#include "cs.h"
/* y = A*x+y */
csi cs_gaxpy (const cs *A, const double *x, double *y)
{
csi p, j, n, *Ap, *Ai ;
double *Ax ;
if (!CS_CSC (A) || !x || !y) return (0) ; /* check inputs */
n = A->n ; Ap = A->p ; Ai = A->i ; Ax = A->x ;
for (j = 0 ; j < n ; j++)
{
for (p = Ap [j] ; p < Ap [j+1] ; p++)
{
y [Ai [p]] += Ax [p] * x [j] ;
}
}
return (1) ;
}
关于python - 如何并行化 scipy 稀疏矩阵乘法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16814273/
我是 python 的新手。我试图找到我的文本的频率分布。这是代码, import nltk nltk.download() import os os.getcwd() text_file=open(
我对安卓 fragment 感到困惑。我知道内存 fragment 但无法理解什么是 android fragment 问题。虽然我发现很多定义,比如 Android fragmentation re
尝试对 WordPress 进行 dockerise 我发现了这个场景: 2个数据卷容器,一个用于数据库(bbdd),另一个用于wordpress文件(wordpress): sudo docker
这个问题已经有答案了: From the server is there a way to know that my page is being loaded in an Iframe (1 个回答)
我正在玩小型服务器,试图对运行在其上的服务进行docker化。为简化起见,假设我必须主要处理:Wordpress和另一项服务。 在Docker集线器上有许多用于Wordpress的图像,但是它们似乎都
我想要发生的是,当帐户成功创建后,提交的表单应该消失,并且应该出现一条消息(取决于注册的状态)。 如果成功,他们应该会看到一个简单的“谢谢。请检查您的电子邮件。” 如果不是,那么他们应该会看到一条适当
就是这样,我需要为客户添加一个唯一标识符。通过 strip 元数据。这就是我现在完全构建它的方式,但是我只有最后一部分告诉我用户购买了哪个包。 我试着看这里: Plans to stripe 代码在这
我有一个类将执行一些复杂的操作,涉及像这样的一些计算: public class ComplexAction { public void someAction(String parameter
这个问题已经有答案了: maven add a local classes directory to module's classpath (1 个回答) 已关闭10 年前。 我有一些不应更改的旧 E
我使用 fragment 已经有一段时间了,但我经常遇到一个让我烦恼的问题。 fragment 有时会相互吸引。现在,我设法为此隔离了一个用例,它是这样的: Add fragment A(也使用 ad
我的 html 中有一个 ol 列表,上面有行条纹。看起来行条纹是从数字后面开始的。有没有办法让行条纹从数字开始? 我已经包含了正在发生的事情的片段 h4:nth-child(even) {
如何仅使用 css 将附加图像 html 化? 如果用纯 css 做不到,那我怎么能至少用一个图像来做 最佳答案 这不是真正的问题,而是您希望我们为您编写代码。我建议您搜索“css breadcrum
以下是 Joshua 的 Effective Java 的摘录: If you do synchronize your class internally, you can use various te
在这里工作时,我们有一个框向业务合作伙伴提供 XML 提要。对我们的提要的请求是通过指定查询字符串参数和值来定制的。其中一些参数是必需的,但很多不是。 例如,我们要求所有请求都指定一个 GUID 来标
我有 3 个缓冲区,其中包含在 32 位处理器上运行的 R、G、B 位数据。 我需要按以下方式组合三个字节: R[0] = 0b r1r2r3r4r5r6r7r8 G[0] = 0b g1g2g3g4
我最近发现了关于如何使用 History.js、jQuery 和 ScrollTo 通过 HTML5 History API 对网站进行 Ajax 化的要点:https://github.com/br
我们有一个 Spring Boot 应用程序,由于集成需要,它变得越来越复杂——比如在你这样做之后发送一封电子邮件,或者在你之后广播一条 jms 消息等等。在寻找一些更高级别的抽象时,我遇到了 apa
我正在尝试首次实施Google Pay。我面临如何指定gateway和gatewayMarchantId的挑战。 我所拥有的是google console帐户,不知道在哪里可以找到此信息。 priva
昨天下午 3 点左右,我为两个想要从一个 Azure 帐户转移到另一个帐户的网站设置了 awverify 记录。到当天结束时,Azure 仍然不允许我添加域,所以我赌了一把,将域和 www 子域重新指
我正在使用terms facet在elasticsearch服务器中获取顶级terms。现在,我的标签"indian-government"不被视为一个标签。将其视为"indian" "governm
我是一名优秀的程序员,十分优秀!