【发布时间】:2013-05-29 18:01:57
【问题描述】:
我在 CUDA 中构建了一个基本内核来执行两个复向量的 elementwise 向量-向量乘法。内核代码插入下面(multiplyElementwise)。它工作正常,但由于我注意到其他看似简单的操作(如缩放矢量)在 CUBLAS 或 CULA 等库中进行了优化,我想知道是否可以通过库调用替换我的代码?令我惊讶的是,CUBLAS 和 CULA 都没有这个选项,我试图通过使其中一个向量成为对角矩阵向量乘积的对角线来伪造它,但结果非常慢。
作为最后的手段,我尝试自己优化这段代码(参见下面的multiplyElementwiseFast),将两个向量加载到共享内存中,然后从那里开始工作,但这比我的原始代码慢。
所以我的问题:
- 是否有执行元素向量-向量乘法的库?
- 如果没有,我可以加速我的代码 (
multiplyElementwise) 吗?
任何帮助将不胜感激!
__global__ void multiplyElementwise(cufftComplex* f0, cufftComplex* f1, int size)
{
const int i = blockIdx.x*blockDim.x + threadIdx.x;
if (i < size)
{
float a, b, c, d;
a = f0[i].x;
b = f0[i].y;
c = f1[i].x;
d = f1[i].y;
float k;
k = a * (c + d);
d = d * (a + b);
c = c * (b - a);
f0[i].x = k - d;
f0[i].y = k + c;
}
}
__global__ void multiplyElementwiseFast(cufftComplex* f0, cufftComplex* f1, int size)
{
const int i = blockIdx.x*blockDim.x + threadIdx.x;
if (i < 4*size)
{
const int N = 256;
const int thId = threadIdx.x / 4;
const int rem4 = threadIdx.x % 4;
const int i4 = i / 4;
__shared__ float a[N];
__shared__ float b[N];
__shared__ float c[N];
__shared__ float d[N];
__shared__ float Re[N];
__shared__ float Im[N];
if (rem4 == 0)
{
a[thId] = f0[i4].x;
Re[thId] = 0.f;
}
if (rem4 == 1)
{
b[thId] = f0[i4].y;
Im[thId] = 0.f;
}
if (rem4 == 2)
c[thId] = f1[i4].x;
if (rem4 == 0)
d[thId] = f1[i4].y;
__syncthreads();
if (rem4 == 0)
atomicAdd(&(Re[thId]), a[thId]*c[thId]);
if (rem4 == 1)
atomicAdd(&(Re[thId]), -b[thId]*d[thId]);
if (rem4 == 2)
atomicAdd(&(Im[thId]), b[thId]*c[thId]);
if (rem4 == 3)
atomicAdd(&(Im[thId]), a[thId]*d[thId]);
__syncthreads();
if (rem4 == 0)
f0[i4].x = Re[thId];
if (rem4 == 1)
f0[i4].y = Im[thId];
}
}
【问题讨论】:
-
"elementwise vector-vector multiplication" 你的意思是点积吗?
-
@Benc... 不。对于实向量,点积是元素乘积的总和。
-
@sgar91:如果他正在“乘”复数,他实际上可能想要计算一个倍半线性形式,在这种情况下可以称为内积/点积(参见 this)。我只是想确定他的意图。
标签: cuda complex-numbers cublas