我不时会读到Fortran是或者可以比C更快进行繁重的计算.这是真的吗?我必须承认我几乎不知道Fortran,但到目前为止我见过的Fortran代码并没有表明该语言具有C所没有的功能.
如果是真的,请告诉我原因.请不要告诉我哪些语言或库对数字运算有好处,我不打算写一个app或lib来做那个,我只是很好奇.
我正在使用一些相当大的,密集的numpy浮点数组,这些数组目前驻留在PyTables CArray的磁盘上.我需要能够执行使用这些阵列效率点的产物,例如C = A.dot(B),其中A是一个巨大的(〜1E4 X 3E5 FLOAT32)存储器映射阵列,以及B和C较小numpy的数组,其驻留在核心存储器.
我现在正在做的是使用数据将数据复制到内存映射的numpy数组中np.memmap,然后np.dot直接调用内存映射数组.这是有效的,但我怀疑标准np.dot(或者它调用的底层BLAS函数)在计算结果所需的I/O操作数量方面可能不是很有效.
我在这篇评论文章中遇到了一个有趣的例子.使用3x嵌套循环计算的天真点积,如下所示:
def naive_dot(A, B, C):
for ii in xrange(n):
for jj in xrange(n):
C[ii,jj] = 0
for kk in xrange(n):
C[ii,jj] += A[ii,kk]*B[kk,jj]
return C
Run Code Online (Sandbox Code Playgroud)
需要O(n ^ 3)个 I/O操作来计算.
但是,通过在适当大小的块中处理数组:
def block_dot(A, B, C, M):
b = sqrt(M / 3)
for ii in xrange(0, n, b):
for jj in xrange(0, n, b):
C[ii:ii+b,jj:jj+b] = …Run Code Online (Sandbox Code Playgroud) 我有一个用C++编写的循环,它是为一个大整数数组的每个元素执行的.在循环内部,我屏蔽了整数的一些位,然后找到最小值和最大值.我听说如果我使用SSE指令进行这些操作,它将比使用按位AND和if-else条件写入的普通循环运行得快得多.我的问题是我应该参加这些SSE指令吗?此外,如果我的代码在不同的处理器上运行会发生什么?它仍然可以工作或这些指令是特定于处理器的吗?
假设我们采用np.dot两个'float32'2D数组:
res = np.dot(a, b) # see CASE 1
print(list(res[0])) # list shows more digits
Run Code Online (Sandbox Code Playgroud)
[-0.90448684, -1.1708503, 0.907136, 3.5594249, 1.1374011, -1.3826287]
Run Code Online (Sandbox Code Playgroud)
数字。除了它们可以更改:
案例1:切片a
np.random.seed(1)
a = np.random.randn(9, 6).astype('float32')
b = np.random.randn(6, 6).astype('float32')
for i in range(1, len(a)):
print(list(np.dot(a[:i], b)[0])) # full shape: (i, 6)
Run Code Online (Sandbox Code Playgroud)
[-0.9044868, -1.1708502, 0.90713596, 3.5594249, 1.1374012, -1.3826287]
[-0.90448684, -1.1708503, 0.9071359, 3.5594249, 1.1374011, -1.3826288]
[-0.90448684, -1.1708503, 0.9071359, 3.5594249, 1.1374011, -1.3826288]
[-0.90448684, -1.1708503, 0.907136, 3.5594249, 1.1374011, -1.3826287]
[-0.90448684, -1.1708503, 0.907136, 3.5594249, 1.1374011, -1.3826287] …Run Code Online (Sandbox Code Playgroud) 我目前正在尝试在Cython中实现基本的矩阵向量乘法(作为一个更大的项目的一部分,以减少计算),并发现我的代码比大约慢2 倍Numpy.dot.
我想知道是否有一些我错过的导致减速的东西.我正在编写优化的Cython代码,声明变量类型,需要连续的数组,并避免缓存未命中.我甚至尝试将Cython作为包装器并调用本机C代码(见下文).
我想知道:我还能做些什么来加快我的实施速度,因此NumPy可以像这个基本操作一样快速运行?
我正在使用的Cython代码是beow:
import numpy as np
cimport numpy as np
cimport cython
DTYPE = np.float64;
ctypedef np.float64_t DTYPE_T
@cython.boundscheck(False)
@cython.wraparound(False)
@cython.nonecheck(False)
def matrix_vector_multiplication(np.ndarray[DTYPE_T, ndim=2] A, np.ndarray[DTYPE_T, ndim=1] x):
cdef Py_ssize_t i, j
cdef Py_ssize_t N = A.shape[0]
cdef Py_ssize_t D = A.shape[1]
cdef np.ndarray[DTYPE_T, ndim=1] y = np.empty(N, dtype = DTYPE)
cdef DTYPE_T val
for i in range(N):
val = 0.0
for j in range(D):
val += A[i,j] * x[j] …Run Code Online (Sandbox Code Playgroud) 我有两个NxN矩阵,我想将它们相乘:A和B.在NumPy中,我使用了:
import numpy as np
C = np.dot(A, B)
Run Code Online (Sandbox Code Playgroud)
然而,我碰巧知道对于矩阵B,只有行n和列n是非零的(这直接来自产生矩阵的分析公式,并且毫无疑问总是如此).
希望利用这一事实并减少产生C所需的乘法次数,我将上述内容替换为:
import numpy as np
for row in range(0, N):
for col in range(0, N):
if col != n:
C[row, col] = A[row, n]*B[n, col] #Just one scalar multiplication
else:
C[row, col] = np.dot(A[row], B[:, n])
Run Code Online (Sandbox Code Playgroud)
从分析上看,这应该降低总复杂度如下:在一般情况下(不使用任何奇特的技巧,只是基本矩阵乘法)C = AB,其中A和B都是NxN,应该是O(N ^ 3).也就是说,所有N行必须乘以所有N列,并且这些点积中的每一个包含N次乘法=> O(N N N)= O(N ^ 3).
然而,如上所述,利用B的结构应当为O(N ^ 2 + N ^ 2)= O(2N ^ 2)= O(N ^ 2).也就是说,所有N行必须乘以所有N列,但是,对于所有这些行(除了那些涉及'B [:,n]'的那些),只需要一个标量乘法:只有一个'B [:,m]'的元素对于m!= n,它不为零.当n == m时,将发生N次(对于必须乘以B的n列的A的每一行一次),必须发生N个标量乘法.
但是,第一个代码块(使用np.dot(A,B))要快得多.我知道(通过以下信息:为什么矩阵乘法比numpy更快,而不是Python中的ctypes?)np.dot的低级实现细节很可能归咎于此.所以我的问题是:如何在不牺牲NumPy的实现效率的情况下利用矩阵B的结构来提高乘法效率,而不在c中构建我自己的低级矩阵乘法? …
该问题涉及基本矩阵运算。在下面的代码中,c1 本质上等于 c2。然而,第一种计算方式比第二种方式快得多。事实上,一开始我以为第一种方式需要分配比a矩阵大两倍的ab矩阵,因此可能会更慢。结果恰恰相反。为什么?
import time
import numpy as np
a = np.random.rand(20000,100)+np.random.rand(20000,100)*1j
tic = time.time()
b = np.vstack((a.real,a.imag))
c1 = b.T @ b
t1 = time.time()-tic
tic = time.time()
c2 = a.real.T @ a.real+a.imag.T@a.imag
t2 = time.time()-tic
print('t1=%f. t2=%f.'%(t1,t2))
Run Code Online (Sandbox Code Playgroud)
一个示例结果是
t1=0.037965. t2=4.375873.
Run Code Online (Sandbox Code Playgroud)