2015-12-11 180 views
1

我想在Julia做一些矩阵乘法,以便将它与numpy的基准相乘。Julia矩阵乘法比numpy的要慢

我朱莉娅代码如下:

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

myFunc() 

而Python版本是:100ms的下

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

的Python版本需要执行。茱莉亚版本超过13岁!看到他们正在使用几乎相同的BLAS技术,Julia版本似乎有问题?!

回答

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

谢谢您为我启发Senderle。 numpy中的以下代码所需时间比Julia版本更长: A = np.mat(np.random.rand(10000,10000)); B = np.mat(np.random.rand(10000,10000)); C = A * B –

+0

哦,是的,非常好的一点! (脸红) –

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秒左右的时间。 (再次,更严重的是,我会用一条直线对对数坐标图进行推断。)