更快的版本:
__global__ void convAgB(double *a, double *b, double *c, int sa, int sb)
{
int i = (threadIdx.x + blockIdx.x * blockDim.x);
int idT = threadIdx.x;
int out,j;
__shared__ double c_local [512];
c_local[idT] = c[i];
out = (i > sa) ? sa : i + 1;
j = (i > sb) ? i - sb + 1 : 1;
for(; j < out; j++)
{
if(c_local[idT] > a[j] + b[i-j])
c_local[idT] = a[j] + b[i-j];
}
c[i] = c_local[idT];
}
**Benckmark:**
Size A Size B Size C Time (s)
1000 1000 2000 0.0008
10k 10k 20k 0.0051
100k 100k 200k 0.3436
1M 1M 1M 43,327
旧版本,
对于1000到100000之间的尺寸,我使用这个朴素版本进行了测试:
__global__ void convAgB(double *a, double *b, double *c, int sa, int sb)
{
int size = sa+sb;
int idT = (threadIdx.x + blockIdx.x * blockDim.x);
int out,j;
for(int i = idT; i < size; i += blockDim.x * gridDim.x)
{
if(i > sa) out = sa;
else out = i + 1;
if(i > sb) j = i - sb + 1;
else j = 1;
for(; j < out; j++)
{
if(c[i] > a[j] + b[i-j])
c[i] = a[j] + b[i-j];
}
}
}
我用一些随机的双精度数字填充了数组a
和b
,并用999999填充了c
(仅用于测试)。使用您的函数(未进行任何修改)验证了c
数组(在CPU中)。
我还从内部循环中删除了条件语句,因此它将只测试一次。
我不是100%确定,但我认为以下修改是有道理的。由于你有 i - j >= 0
,这与 i >= j
相同,这意味着一旦j > i
,就永远不会进入这个块'X'(因为j ++):
if(c[i] > a[j] + b[i-j])
c[i] = a[j] + b[i-j];
在变量out
上计算循环条件,如果i > sa
,则意味着当j == sa
时循环将结束;如果i < sa
,则意味着由于条件i >= j
的存在,循环将在i + 1
时(更早地)结束。
另一个条件i - j < size(b)
意味着当i > size(b) + 1
时,将开始执行块“X”,因为j
始终等于1。因此,我们可以将j
设置为应该开始的值,如下:
if(i > sb) j = i - sb + 1;
else j = 1;
请尝试使用真实的数据数组测试此版本,并给我反馈。欢迎任何改进意见。
编辑:可以实现一项新的优化,但这并没有什么大的区别。
if(c[i] > a[j] + b[i-j])
c[i] = a[j] + b[i-j];
我们可以通过以下方式消除if语句:
double add;
...
for(; j < out; j++)
{
add = a[j] + b[i-j];
c[i] = (c[i] < add) * c[i] + (add <= c[i]) * add;
}
需要:
if(a > b) c = b;
else c = a;
这段代码的意思是 c = (a < b) * a + (b <= a) * b。
如果 a > b,那么 c = 0 * a + 1 * b;=> c = b;
如果 a <= b,那么 c = 1*a + 0 *b; => c = a;
**Benckmark:**
Size A Size B Size C Time (s)
1000 1000 2000 0.0013
10k 10k 20k 0.0051
100k 100k 200k 0.4436
1M 1M 1M 47,327
我正在测量从CPU复制到GPU、运行内核和从GPU复制到CPU所需的时间。
GPU Specifications
Device Tesla C2050
CUDA Capability Major/Minor 2.0
Global Memory 2687 MB
Cores 448 CUDA Cores
Warp size 32