cuda 计算1维的卷积

1维卷积的公式如下.

result = conv(a,b); result(k)=\sum_{i=0}^{k}a[i]b[k-i]

用c++串行计算,程序如下:

void conv(vector<int> &uIn, vector<int>&vIn, vector<int>&convOut)
{
	vector<int>::iterator itU = uIn.begin();
	vector<int>::iterator itV = vIn.begin();

	convOut.clear();

	int uSize = uIn.size();
	int vSize = vIn.size();
	int numResult = uSize + vSize - 1;
	convOut.resize(numResult);

	for (int i = 0; i<numResult; i++)
	{
		convOut[i] = 0;
		for (int j = 0; j <= i; j++)
		{
			int k = i - j;
			int tempU = j<uSize ? uIn[j] : 0;
			int tempV = k<vSize ? vIn[k] : 0;
			convOut[i] += tempU*tempV;
		}
	}
}

现在需要在cuda上面进行并行计算,先进行并行化的算法设计:

一,总体思路,

  1. 将数据分割成块,每个块单独计算。
  2. 将数据进行合并。

二,具体法,

  1. 分割成32x32的块(a中依次取32个数,b依次取32个数),每个块内进行计算。
  2. 每个32x32的块中,计算如下:

2.1,生成矩阵如下:

如果是4x4,那么类似的矩阵如下:

a0*b0

0

0

0

a0*b1

a1*b0

0

0

a0*b2

a1*b1

a2*b0

0

a0*b3

a1*b2

a2*b1

a3*b0

0

a1*b3

a2*b2

a3*b1

0

0

a2*b3

a3*b2

0

0

0

a3*b3

0

0

0

0

矩阵大小为8x4,其中第8行为全0,只是为了内存对齐。 a为1个数组,b为另1个数组。那么对于32x32的输入,那么生成的矩阵大小为64x32,最后一行也是全0。 

2.2,将矩阵的每一行的数据相加,得到一个累加和,那么64行,就有64个结果。这64个结果就是这个32x32的卷积结果。

2.3, 将结果存入一片内存中,格式如下:

对于总长128x128(数组a的长度为128,数组b的长度为128)的数据,内存格式如下:

这个矩阵的宽和高等于length(a)/32. length(b)/32这个矩阵中,每个元素包含一个数组,长度为64,也就是2.2步的计算结果3

3. 合并的第一步是将2.3中的数据格式进行转换,转换结果如下:

这个矩阵中,每一个元素包含32个数据,这个32个数据是通过取2.3结果中的一个元素(下标为ia,ib)的前32个值,再取这个元素的上一行对应的元素(下标为ia-1,ib)的后32个值,然后对应相加。这部分的matlab程序如下:

blocksStep2 = cell(blockNumY*2,blockNumX); 

for ix = 1:blockNumX

    for iy = 1:(blockNumY + 1)

        currArr32 = zeros(1,32);

        if(iy<=blockNumY)

            currArr32 = blocksStep1{iy,ix}(1:32);

        end

        lastArr32 = zeros(1,32);

        if(iy>1)

            lastArr32 = blocksStep1{iy-1,ix}(33:64);

        end

        blocksStep2{iy+ix-1,ix} = currArr32+lastArr32;

    end

end

其中blockNumY为2.3结果矩阵的总行数,blockNumX为2.3结果矩阵的总列数。

4.将第3步的结果矩阵中的每一个元素中的32个数据 进行 列排列,1x32 à32x1。然后将矩阵的每一行的4个32x1数组拼接成一个32x4的矩阵。然后将这个32x4的矩阵的每一行的值进行相加,就得到32个数据。对应于第3步的矩阵中,每一行会有32个数据结果。然后将所有结果按顺序保存下来,得到最后的结果,数据个数为32x8最后一个数据无效,那么有效数据个数为32x8 – 1.

5.此文中,以128长度的数组为例进行解释,对于1024长度的数据,也是一样的道理,那么2.3的结果矩阵大小为32x32,第3步的结果矩阵大小为64x32.最后的总的结果数为64x32-1.

测试结果如下:

1,电脑配置:CPU, intel pentinum G860@ 3.00Ghz双核。

                          GPU,nvidia Geforce GTX 1060 3G (七彩虹)

2,数据长度,a的长度为1024,b的长度为1024

3,结果如下:

cuda conv cost 0.001453s
sum is 1074003968
cpu conv cost 0.294342s
sum is 1074003968

GPU还是很有优势的,如果把CPU换成高性能的,应该不用花费290ms这么多,但是也比不上GPU快

测试程序在https://gitee.com/yt2014/cuda-programs/tree/master/conv_1d

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值