Julia矩阵乘法比numpy的

时间:2015-12-11 12:01:41

标签: python numpy julia matrix-multiplication blas

我正在尝试在Julia中进行一些矩阵乘法,以便将其与numpy进行对比。

我的朱莉娅代码如下:

function myFunc()
  A = randn(10000, 10000)
  B = randn(10000, 10000)
  return A*B
end

myFunc()

python版本是:

A = np.random.rand(10000,10000)
B = np.random.rand(10000,10000)
A*B

Python版本需要不到100毫秒才能执行。 Julia版本需要超过13秒!看到他们在引擎盖下使用几乎相同的BLAS技术,似乎是Julia版本的问题?!​​

2 个答案:

答案 0 :(得分:12)

我不认为那些人在做同样的事情。 numpy表达式只进行逐元素乘法运算,而Julia表达式进行真正的矩阵乘法运算。

您可以使用较小的输入来查看差异。这是numpy示例:

>>> A
array([1, 2, 3])
>>> B
array([[1],
       [2],
       [3]])
>>> A * B
array([[1, 2, 3],
       [2, 4, 6],
       [3, 6, 9]])
>>> B * A
array([[1, 2, 3],
       [2, 4, 6],
       [3, 6, 9]])

请注意,这里我们有广播,其中"模拟"两个向量的外积,所以你可能会认为它是矩阵乘法。但它不可能,因为矩阵乘法不是可交换的,而且(A * B) == (B * A)。看看在朱莉娅做同样的事情会发生什么:

julia> A = [1, 2, 3]
3-element Array{Int64,1}:
 1
 2
 3

julia> B = [1 2 3]
1x3 Array{Int64,2}:
 1  2  3

julia> A * B
3x3 Array{Int64,2}:
 1  2  3
 2  4  6
 3  6  9

julia> B * A
1-element Array{Int64,1}:
 14

在这里,B * A为您提供了正确的点积。如果您想进行真正的比较,请尝试numpy.dot

如果您使用的是Python 3.5或更高版本,您还可以使用新的内置点积运算符!只需确保矩阵的形状对齐:

>>> A
array([[1, 2, 3]])
>>> B
array([[1],
       [2],
       [3]])
>>> A @ B
array([[14]])
>>> B @ A
array([[1, 2, 3],
       [2, 4, 6],
       [3, 6, 9]])

答案 1 :(得分:3)

朴素矩阵乘法采用N ^ 3个运算的顺序。你可以做一个简单的基准来看看这种增长:

function myFunc(N)
    A = rand(N, N)
    B = rand(N, N)

    A*B
end

myFunc(1)   # run once to compile

sizes = [floor(Int, x) for x in logspace(1, 3.5, 50)]

times = [@elapsed(myFunc(n)) for n in sizes]

using PyPlot

loglog(sizes, times, "o-")

为了更严肃地做到这一点,我会在每个尺寸上平均几次跑步。 我得到类似下图的内容。enter image description here 实际上,推断到N = 10 ^ 4会在我的计算机上产生大约20或30秒的时间。 (同样,更严重的是,我会在对数 - 对数图中使用直线来进行推断。)