请问,一样的cuda代码在32位系统上跑的速度比在64位系统上跑的要快很多,这时为什么?
楼主您好!
对于您的疑问,我表示:快得多不至于。快一些还是可以的。
因为X64下很多数据需要更多的资源,例如指针,需要占用2个连续的寄存器而不是1个。
因为存在着更多的更多的资源占用,导致您的kernel因为寄存器压力等,可能导致无法有更高的occupancy,以及可能导致更大的local memory traffic压力,从而导致性能多少下降。
综上所述,所以您能感觉32位下kernel稍微快一些。但快很多我不认为是合理的。
但是,代码跑出来的结果是64位系统用的时间大概是32位系统的10倍?难道代码有问题?
如果您的代码的确在32位比在64位下下能快10倍,那么我的解释就无法对上了。
我建议您咨询WangPeng同学。您可以直接给他留言。
或者您也可以检查下自己的代码,看看是否有问题。
通过简单的更换64/32位系统,就能提速10倍。我认为不太可能。
嗯,所以很奇怪。
另外想请教个问题,我在做一个汉语拼音匹配的程序,我的思路是这样的,希望给点意见,最好在并行模型上能给点建议:
1设字典有d行,那么我开了d个线程,每个block设置256个线程,一个线程对应字典的一行,字典每一行都是不一样的;
2对于每一个线程,也就是字典的每一行,在待匹配词语里查找,如果找到一样的,就标志这个词语匹配成功,继续下一个词语匹配,因为待匹配的词语中可能有相同的。
3没匹配成功的词语都拆分成单个字,继续并行匹配这些字
以上是我的思路,通过结果发现并行的速度并不一定会比串行的快。请大家帮帮忙!
楼主您好!
您的描述中有一些不明确的地方。
(1)您的字典的一行指的是什么?一个字符串吗?
(2)带匹配词语是什么?一个字符串吗?
(3)“如果找到一样”指的是什么?是(a)待匹配字符串里包含从字典里来的字符串吗?还是(b)字典字符串和带匹配字符串完全一致?
(4)您如何定义您的“比较一致”这个操作?例如(a) 'A’和’a’算一致. (b)'A’和’a’不算一致。(c)某些unicode字符的含有多种重音的变体被认为一致。(d)某些unicode字符的含有多种变音的字体被认为不一致。(e)所有的unicode空白字符都被认为是一致的。(f)unicode空白字符和空白字符被认为是不一致的。所以您需要给出准确的“比较一致”的定义。
(5)您的“如果待匹配词语没有匹配成功,则继续下一个词语匹配,因为待匹配的词语中可能有相同的。”这句话无法理解。建议您重写此话。
(6)您的“没匹配成功的词语都拆分成单个字,继续并行匹配这些字”。此话也无法理解。因为缺乏前置的概念“词语”和“字”。他们都表示什么?字符串和其中的字符吗?还是其他含义。
(7)您的字典的存储结构是?您的待匹配字符的存储模型是?
希望您回答以上问题,以及给出一些词语的定义。以便让其他会员/版主为您设计。
感谢您的来访,祝您假日愉快!
词语就是平时的中文词语,比如“中国”,是字符串;
字典里就是一个字符串数组,里面包行很多的词语;
匹配成功就是词语与字典里的词语完全一样,这里只匹配中文词语;
比如“中国”这个词语在字典里匹配不成功,也就是字典里没有这个词语,那么把“中国”拆分成两个词语“中”和“国”,在并行处理这两个词语;
比如待测词语有“中国”,“美国”,“英国”,“中国”,那么如果当前线程所对应的字典一行是“中国”,就会匹配两次,也就是第一次匹配到“中国“成功,会继续匹配下一个待匹配词语;
字典与待匹配词语都是字符串存储在二维数组里。
收到回复。我不懂这些。
建议其他会员/版主(例如WangPeng, Tianyuan2008)等上线后,让他们为您设计您的算法。
感谢您的莅临。
祝您假日愉快!
不懂此类算法,隐约觉得可能在访存方面的效率不高,功能方面按照你的叙述似乎是可以的。
无责任评价完毕,欢迎补充。
建议LZ等待其他会员/版主上线讨论。
祝您编码愉快~
1.尽量避免WARP内分支
2.合并访问
看看如上两条是否注意了。
这个怎么避免,是线程数分配的问题嘛?
看来你还没有优化。
没有针对GPU优化过的程序谈性能恐怕意义不大。
不优化就能高效率运行是一个梦啊。
努力吧。
好吧。谢谢啦
我的习惯是,先写正确,然后考虑是否需要优化。
楼主不妨也这样,我多年的实践告诉我,这样比较好,避免走弯路。
当然,楼主也可以尝试自己的路…
确实如此。
如果程序能够简单修改,正确运行。
然后简单优化,得到很好地性能。
节省时间,提高工作效率。
这是大家都期待的…
还有一个原因是:实际的瓶颈和运行情况,与事先预想不同。这样与其事先苦苦根据预想的情况调整,不如先给出一个实现,看看到底如何。
楼主你好,
从你描述的问题来看,首先你的程序绝对是非合并访问形式。比如你有256行,那么每个线程将从不同段开始访问,CUDA是以WARP为访问内存的基本单位,那么一个WARP里就需要32次从GLOBAL MEMORY读取内存,而访问GLOBAL MEMORY至少需要400个CYCLE,所以就是32*400个CYCEL,这样会严重增加访问内存的时间,导致你的程序执行速度会很慢。当然你的程序不可避免的会出现分支,所以要优化的话我建议重点还是放在内存的访问方面。
如果要从内存方面优化,那么需要楼主提供一些基本的信息,比如你的一行每个词的长度是否固定,也就是说一个词是否占用的BYTE是相同的?假设长度固定,那么再设计算法就简单一些了。比如你有256个词,每个词大小是4BYTE,那么我可以用256个线程把这256个词只用一次global memory访问读取到shared memory,再做匹配处理。
具体的算法设计还是要看楼主具体的问题,我只提供一个建议,按照上面的方法,用合并访问的方式将数据读入shared memory(这个比global memory访问速度快百倍),再从shared memory里进行处理,会极大的提高内存的访问性能。
这个确实是一个问题。
其实以前CPU编程,有很多硬件的东西不清楚,所以优化起来很棘手。
这个棘手并不是逻辑上的问题,而是对硬件不了解,无从下手。
现在到了GPU,有了一些资料,感觉比CPU更透明了,所以心理上感觉更有信心了。
说实在的,现在更需要的是对硬件信息更详尽的了解,这样在软件设计上就可以一举达到最大效率。
而不是像以前CPU编程那样瞎猜。
包括我在内,我想很多人都是这样的一种状态。尤其是对于具有多年编程经验的老手。
需要的仅仅是对硬件的更深入的了解。无它而。
感谢songyong2同学积极回帖参与讨论。
其实CPU的优化也是有相关的参考手册的,这一点横扫千军斑竹比较有心得,他看过很多这样的官方手册。
但另一方面,人工优化的话,有可能取得更高的效率,也有可能因为操作不当而损失效率。很多情况下,让编译器代为决定是方便合理的。可能更好的方法是,熟悉硬件特性,调整,跑profile,看自动优化情况如何,看手工调整情况如何,等等反复优化。
同时,硬件总是推陈出新的,如果你是在固定的目标硬件上跑,那么详细的手工优化可能更有意义一些。如果是不同版本的硬件,可能会损失效率甚至出问题。而且手工优化总是要耗费更多的开发时间。
所以,这其实是一个有些矛盾的问题,往往需要一个平衡点。平衡性能和兼容性,平衡开发成本和性能。像runtime API并没有driver API提供的功能多,但是他解决了绝大部分问题,而且非常便于使用,使得一般的非CS科班的人员也能用CUDA来解决问题。
最后,无论什么情况下,对细节,和真理的追求都是十分美好的,孜孜以求地探索细节,追求尽善尽美,是十分可贵的品质,愿共勉!
欢迎您莅临论坛,祝您编码愉快~
如果是非合并访问的话,例如17#所说的完全非合并访问,那么最主要的访存损失是带宽的问题。因为每次访存都会丢弃很多数据,这导致有大量的带宽被浪费。同时会使掩盖延迟的压力有所提升,因为实际需要访问global的次数增多了。
但,延迟只是一个影响方面,我认为带宽的损失或许是更为严重的问题。
欢迎大家补充/讨论/指正。