在循环

时间:2015-04-30 15:30:48

标签: python loops theano

我已经安装了Theano库来提高计算速度,这样我就可以使用GPU的强大功能。

但是,在计算的内部循环中,根据循环索引和几个数组的相应值计算新索引。

然后,该计算的索引用于访问另一个数组的元素,而该数组又用于另一个计算。

这太复杂了,不能指望Theano有任何显着的加速吗?

所以让我重新解释一下我的问题,反之亦然。 以下是GPU代码段的示例。由于简洁起见,省略了一些初始化。我可以将其转换为Python / Theano而不会大幅增加计算时间吗?

__global__ void SomeKernel(const cuComplex* __restrict__  data,
                                 float* __restrict__ voxels)

{

unsigned int idx = blockIdx.x * blockDim.x + threadIdx.x;

unsigned int idy = blockIdx.y * blockDim.y + threadIdx.y;

unsigned int pos = (idy * NX + idx);

unsigned int ind1 = pos * 3;
float x = voxels[ind1];
float y = voxels[ind1 + 1];
float z = voxels[ind1 + 2];

int m;

for (m = 0; m < M; ++m)
{
    unsigned int ind2 = 3 * m;

    float diff_x = x - some_pos[ind2];
    float diff_y = y - some_pos[ind2 + 1];
    float diff_z = z - some_pos[ind2 + 2];

    float distance = sqrtf(diff_x * diff_x
                         + diff_y * diff_y
                         + diff_z * diff_z);

    unsigned int dist = rintf(distance/some_factor);
    ind3 = m * another_factor + dist;

    cuComplex some_element = data[ind3];

    Main calculation starts, involving some_element.

2 个答案:

答案 0 :(得分:4)

不,我看不到任何使用张量而不是for循环无法完成的事情。这应该意味着您可能会看到速度的增加,但这实际上取决于应用程序。你有一个python + theano的开销,特别是来自类似c的代码。

所以,而不是

for (m = 0; m < M; ++m)
{
    unsigned int ind2 = 3 * m;

    float diff_x = x - some_pos[ind2];
    float diff_y = y - some_pos[ind2 + 1];
    float diff_z = z - some_pos[ind2 + 2];

    float distance = sqrtf(diff_x * diff_x
                         + diff_y * diff_y
                         + diff_z * diff_z);

    unsigned int dist = rintf(distance/some_factor);
    ind3 = m * another_factor + dist;

    cuComplex some_element = data[ind3];
}

你可以做一些像我这样的事情

diff_xyz = T.Tensor([x,y,z]).dimshuffle('x',0) - some_pos.reshape(-1,3)
distance = T.norm(diff_xyz)
dist = T.round(distance/some_factor)
data = data.reshape(another_factor,-1)
some_elements = data[:,dist]

请参阅?没有更多的循环,因此GPU可以平行化。

  

然而,在计算的内部循环内,基于循环索引和一对数组的对应值计算新索引。 (...)这太复杂了,不能指望Theano有任何显着的加速吗?

一般情况下:只要循环索引与所需索引具有线性关系,就可以通过使用张量而不是循环来优化。然而,它需要一点创造力和按摩来做对。

使用Tensor.take()也可以实现非线性关系,但我不敢保证它在GPU上的速度。我的直觉总是告诉我要远离它,因为它可能太灵活而不能很好地优化。但是,当没有其他选择时,可以使用。

答案 1 :(得分:2)

使用全局内存时,GPU在随机存取内存方面表现不佳。我之前没有使用过Theano,但如果你的数组都适合本地内存 - 这会很快,因为随机访问不是问题。如果它是全球记忆,虽然很难预测它会有什么性能,但它与它的全部功率相差甚远。另一方面,这个计算是否可以并行化?只有当这些事情同时发生时,GPU才真正做得很好。