一个关于消除数据依赖性的问题

  1.           for (k = 0; k < max; k++)
  2.                 A[B[k]] *= C[k];
复制代码
   这段代码中A数组是一段包含m个元素的数组,B数组是一段包含 max(max远大于m)个元素的数组,C同样 是一段包含 max个元素的数组。且B数组中所有元素的值都取在0-m之间。       因为这段代码包含着数据依赖性问题,所以不能直接在CUDA上并行,否则取值会有冲突与覆盖的情况。
   由于需要用CUDA并行优化某个程序,类似这样的代码卡在其中,使得并行化受阻,目前只能通过将这段代码转移到CPU执行,执行完后再将结果转回GPU,由于来回传输数据,所以影响了性能。
   那么问题来了,可以用什么方式让这段代码实现并行化,希望大家能给小生一些提示与帮助,在下不胜感激!

这是我之前在论坛提的问题,经过查阅相关资料,现在在这里记录下自己给出的答案。
关于解决办法,我想过很多种方法,最开始的想法是利用原子操作,但是后来发现原子操作具有局限性,因为我们操作的是向量,并不是单一元素,所以不能使用原子操作。

之后想的办法是折叠展开,但是折叠展开针对的是在相邻数量的元素中不包含数据冲突问题的向量。而我们操作的B下标索引数组,其数据极不规律,两个相同数组可能很近,也可能很远,所以折叠展开也不是一个好的办法。

那么是不是没有办法了呢,办法一定有,在所有程序设计中,空间与时间都存在着一种相互制衡的关系,我们可以牺牲时间换取空间,同样,我们可以牺牲空间换取时间上的提升。在这里,因为B数组在整个程序中会反复用到,且B索引数组不会变更,为一定值向量,有了这两个前提,我们便可以采取空间换时间的策略,来完成其并行方法。

首先需要将B索引数组的特征提取出来,也就是将B索引数组按照其从小到大,依次提取出来,并归类搁置,存到一个文件中。由于B是定值向量,我们便再申请一个数组,将特征读取到这个数组中,数组中存储的便是从0-m大小的元素的下标位置。

这样,我们便能够把循环变更成这种形式:

		for (int k = 0; k < m; k++){
			for (int j = 0; j < E[k]; j++){
				A[k] *= C[D[k*width + j]];
			}
		}

其中E数组存着的是从0-m各元素的数量,D数组为新的特征下标。
如此一来,我们变将数据依赖性分割开来,整个程序便可以并行运算,虽然多了一层循环,但是这部分代码不再是不可并行那一部分,我们便可以使整体完全放在kernel上运行,从而去除内存拷贝函数,整个程序相比之前,提速了35%,效果可人!


  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值