Theano中减少操作的加速

时间:2016-01-04 08:34:05

标签: python numpy parallel-processing gpgpu theano

修改
很抱歉,事实证明,当我进行测试时,我在GPU上运行了其他进程,我已经在空闲GPU上更新了时序结果,并且对于更大的矩阵,加速变得明显。

原帖:

this question中发布时,L是一个矩阵列表,其中每个项M都是x*n矩阵(x是变量,{ {1}}已修复)。

我想计算n中所有项目M'*M的总和(LM'的转置),如下面的Python代码所示。

M

以下是Numpy和Theano实现的一些示例(对于可执行脚本,请参阅@ DanielRenshaw对previous question的回答)。

for M in L:
  res += np.dot(M.T, M)

我在CPU上运行Numpy版本,在GPU上使用不同设置运行Theano版本,似乎Theano版本总是比Numpy版本慢一些(无论matices的数量和大小如何)。

但我期待可能有一些优化w.r.t GPU,因为它是一个简单的减少操作。

有人可以帮助我理解幕后发生了什么吗?

编辑:
以下是用于生成数据的脚本(来自@DanielRenshaw),我厌倦了设置和结果。

def numpy_version1(*L):
    n = L[0].shape[1]
    res = np.zeros((n, n), dtype=L[0].dtype)
    for M in L:
        res += np.dot(M.T, M)
    return res

def compile_theano_version1(number_of_matrices, n, dtype):
    L = [tt.matrix() for _ in xrange(number_of_matrices)]
    res = tt.zeros(n, dtype=dtype)
    for M in L:
        res += tt.dot(M.T, M)
    return theano.function(L, res)

def compile_theano_version2(number_of_matrices, n):
    L = theano.typed_list.TypedListType(tt.TensorType(theano.config.floatX, broadcastable=(None, None)))()
    res, _ = theano.reduce(fn=lambda i, tmp: tmp+tt.dot(L[i].T, L[i]),
                           outputs_info=tt.zeros((n, n), dtype=theano.config.floatX),
                           sequences=[theano.tensor.arange(number_of_matrices, dtype='int64')])
    return theano.function([L], res)

1 个答案:

答案 0 :(得分:2)

您遇到的问题不是矩阵的数字,而是 size

您的测试示例,创建的矩阵大小取决于您拥有的矩阵数量,因此,矩阵越大矩阵越多,但python循环开销越大(在reduce操作中),因此,它更难以发现速度改进。

为了进行一些新的测试,我已经对你的矩阵生成进行了明显的修改:

S = 1000 # Size of the matrices
N = 10 # Number of matrices

L = [np.random.standard_normal(size=(np.random.randint(S//2, S*2), S)).astype(np.float32) for _ in range(N)]

这只会生成10个大小为(x, 1000)的矩阵,其中x[S//2, S*2] == [500, 2000]范围内的某个值。

f1 = compile_theano_version1(N, S, np.float32)
f2 = compile_theano_version2(N, S)
  • 现在使用N = 10大矩阵进行一些测试:

对于S = 1000N = 10

 %timeit numpy_version1(*L)   # 10 loops, best of 3: 131 ms per loop
 %timeit f1(*L)               # 10 loops, best of 3: 37.3 ms per loop
 %timeit f2(L)                # 10 loops, best of 3: 68.7 ms per loop

其中theano函数在笔记本电脑中具有x4x2加速,具有非常好的i7和一个不错的NVIDIA 860M(这意味着你应该在这里获得更好的加速)。

对于S = 5000N = 10

 %timeit numpy_version1(*L)   # 1 loops, best of 3: 4 s per loop
 %timeit f1(*L)               # 1 loops, best of 3: 907 ms per loop
 %timeit f2(L)                # 1 loops, best of 3: 1.77 s per loop

因此,总的来说,使用此设置,S越大,theano越过CPU的速度越大。

  • 使用N = 100大矩阵的一些测试:theano似乎更快

对于S = 1000N = 100

%timeit numpy_version1(*L)   # 1 loops, best of 3: 1.46 s per loop
%timeit f1(*L)               # 1 loops, best of 3: 408 ms per loop
%timeit f2(L)                # 1 loops, best of 3: 724 s per loop

对于S = 2000N = 100

%timeit numpy_version1(*L)   # 1 loops, best of 3: 11.3 s per loop
%timeit f1(*L)               # 1 loops, best of 3: 2.72 s per loop
%timeit f2(L)                # 1 loops, best of 3: 4.01 s per loop
  • 使用N = 100小矩阵进行测试:numpy似乎更快

对于S = 50N = 100

%timeit numpy_version1(*L)   # 100 loops, best of 3: 1.17 ms per loop
%timeit f1(*L)               # 100 loops, best of 3: 4.21 ms per loop
%timeit f2(L)                # 100 loops, best of 3: 7.42 ms per loop

测试规格:

  • 处理器:i7 4710HQ
  • GPU:NVIDIA GeForce GTX 860M
  • Numpy:使用intel MKT构建的1.10.2版本
  • Theano:版本0.70; floatX = float32;使用GPU