更快的版本:
__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
使用了一些随机双数和c
999999(仅用于测试)。我使用您的函数(没有任何修改)验证了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
了循环条件 if i > sa
,这意味着循环将在什么时候完成j == sa
,如果这意味着循环将因为条件而i < sa
完成(更早)。i + 1
i >= j
另一个条件i - j < size(b)
意味着您将开始执行块'X',当i > size(b) + 1
因为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