我已经安装了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.
答案 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才真正做得很好。