谈到内存的访问,其实也就是几个API函数的调用,感觉也没什么好讲的,知道cudaMalloc,知道cudaMemcpy,还有cudaFree,就应该可以对device上的内存进行分配,然后就可以在device上使用内存。但是就像我们看运动会一样,只看100米的那不到10秒的时间,也许你只会说,他跑得真快。又有多少人能清楚其过程中的磨炼啦?要真正理解device上内存的调度访问,让我们的程序达到更快的速度,就得对内存访问的情况做更深入的了解,明白其中的过程。
我记得大学刚开始上编程语言的课程的时候,都会讲到内存的分配和内存的释放,但是一般都是在书的最后面才会讲内存的对齐,内存的空间布局。就像C++一样,或许你学习了好几年,用了它好多年,但是你是否清楚class的内存布局?知道虚表是怎么一个内存访问过程?就像做网络,当做到一定地步的时候,才会发现数据从一段传递到另一段的时候数据发生了变化,内容不对了,定义的结构体传递到另一边的时候就错位了。当在使用SSE对数据处理加速的时候,是否为内存对齐的问题头疼?说了这么多,或许有人在烦了~~~讲正题吧,这些部分或许只有自己真正在实际运用中遇到问题,才会去考虑的,不过还是希望大家能在遇到问题之前,就能掌握解决问题的能力。不是在遇到美女的时候才开始刮胡子,平时的习惯就要养好。
前面这一段话或许只是生活的一些经历,其实可以跳过,当遇到的时候再回来看看:)我们还是按部就班的来讲解device上内存的访问吧。这么多年的发展,内存的价格是越来越便宜,但是有谁知道当你做编织内存的时候,很多人的眼睛都被弄瞎过啦,为她们当年为计算机作出的贡献bless一下。
还记得小时候经常看枪战片,看到小马哥端着枪一个劲的扫射,哪个帅啊~~不过后来稍微大一些以后,心理面一直有一个疑问,子弹用不完?一次能装多少子弹啊~就那么小的弹夹。8发子弹的左轮手枪在帅哥哥手里可以搞定十几个人~还不装弹- 囧!一般的自动手枪一般都是8发,14发,最多的驳壳枪(毛瑟枪)也才能装20发子弹。你要说人家是《第一滴血4》里面的史泰龙可以开着战车上面的M2HB12.7mm重机枪,子弹不用弹夹,一次可以装几千发的弹;对,人家是DMA直接内存访问,不是通过弹夹访问的,不需要处理器来中转数据。G80支持的内存访问的能力是一次访问4bytes,8byets或者16bytes,G80有三种弹夹,一种可以一次装4发子弹,一种是8发子弹,还有16发的。
Global Memory 在访问过程中没有Cache,就像以前的火枪一样,打一枪以后,装药,然后才能打下一枪。每次的访问时间是400-600个clock(core 跑的时钟)延迟。所以在CUDA编程中,其中一个瓶颈就是内存访问。利用SDK提供的bandwidthTest可以测试到host到device,device到host,device到device的传输性能。虽然PCIE有3.2G/s的理论值,但实际达不到这么多。Device to Device的传输能达到89G/s(GTX260)左右,理论值是90G/s(GTX260)也达到差不多了。这个地方每个人显卡不一样,主板不一样,设置环境不同,也不一定一样。
Device上active的一个warp有32个线程,但是实际是16个thread同时在运行,就是half warp。当half warp的16个threads访问内存的时候,最好让16个thread依次对着相对应的内存地址,这样的时候才能保证Coalesced Access。如下图http://www.isi.edu/~ddavis/GPU/Course/Slides/GPU+CUDA.pdf: