【问题标题】:Speedup for the reduce operation in TheanoTheano 中 reduce 操作的加速
【发布时间】:2016-04-07 20:03:08
【问题描述】:

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

原帖:

正如this question 中发布的那样,L 是一个矩阵列表,其中每个项目M 是一个x*n 矩阵(x 是一个变量,n 是固定的)。

我想计算L 中所有项目的M'*M 总和(M'M 的转置),就像下面的 Python 代码一样。

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

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

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)

我在 CPU 上运行 Numpy 版本,在 GPU 上运行不同设置的 Theano 版本,似乎 Theano 版本总是比 Numpy 版本慢(不管 matices 的数量和大小)。

但我期待可能会针对 GPU 进行一些优化,因为它是一个简单的 reduce 操作。

有人可以帮助我了解幕后发生的事情吗?

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

L = [np.random.standard_normal(size=(x, n)).astype(dtype)
     for x in range(min_x, number_of_matrices + min_x)]

dtype = 'float32'
theano.config.floatX = dtype
iteration_count = 10
min_x = 20

# base case:
# numpy_version1 0.100589990616
# theano_version1 0.243968963623
# theano_version2 0.198153018951
number_of_matrices = 200
n = 100

# increase matrix size:
# numpy_version1 4.90120816231
# theano_version1 0.984472036362
# theano_version2 3.56008815765
number_of_matrices = 200
n = 1000

# increase number of matrices:
# numpy_version1 5.11445093155
# theano_version1 compilation error
# theano_version2 6.54448604584
number_of_matrices = 2000
n = 100

【问题讨论】:

  • 你有哪个 GPU?这可能是答案的关键。如果你有最新的 i7 和最糟糕的 GPU,不管阵列有多大,CPU 版本可能会更快,特别是如果你有使用 MKL、OpenBLAS 等构建的 numpy。点操作。
  • @imaluengo 正在使用 i7、nvidia titan x,并且 numpy 是使用 OpenBLAS 构建的
  • Ops,那不应该是这样的:P 你能添加你在测试中尝试过的L 的值和M 的大小,以及你得到的结果(至少一些其中)?
  • @imaluengo 谢谢,我会尽快添加它们。
  • 只是为了复制准确的结果。更容易测试出了什么问题。

标签: python numpy parallel-processing gpgpu theano


【解决方案1】:

您遇到的问题不是矩阵的数量,而是它们的大小

您的测试示例创建大小取决于您拥有的矩阵数量的矩阵,因此,您拥有的矩阵越多,矩阵越大,但 python 循环开销也越大(在减少操作中),因此,更难检测到速度的提高。

我已经仔细修改了您的矩阵生成,以便进行一些新的测试:

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 函数在具有相当不错的i7 和不错的 NVIDIA 860M 的笔记本电脑中具有 x4x2 加速(这意味着您应该在这里获得更好的加速)。

对于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:使用英特尔 MKT 构建的 1.10.2 版
  • Theano:版本 0.70;浮动X=浮动32;使用 GPU

【讨论】:

  • 另一个起作用的因素是在主内存和 GPU 内存之间复制数据的开销。 CPU 版本完全避免了这种开销,但我现在还不清楚超参数的变化将如何影响 GPU 速度。它确实需要在真实的使用环境中进行测试,而不是在这种人为的情况下进行测试。
  • @DanielRenshaw 是的,在真实环境中很难说真正的加速是什么。我现在能做的就是添加更多的综合测试:P 刚刚添加了更多具有更大N(矩阵数量)的测试,并且速度不断提高。使用较小的S(矩阵大小),numpy 似乎更快(正如我所期望的那样),因为将矩阵复制到 GPU 的开销大于通过在 GPU 中相乘获得的加速。
猜你喜欢
  • 1970-01-01
  • 2017-12-19
  • 1970-01-01
  • 2016-06-12
  • 2015-05-04
  • 2017-10-19
  • 1970-01-01
  • 1970-01-01
  • 2022-08-14
相关资源
最近更新 更多