GPGPU编程是否只允许执行SIMD指令? 如果是这样,那么重新编写一个算法的任务是一项繁琐的任务,而该算法已被设计为在通用CPU上运行以在GPU上运行?在可以转换为SIMD架构的算法中是否还有 模式?GPGPU编程是否只允许执行SIMD指令?
回答
那么,GPGPU只支持SIMD执行并不完全正确。许多GPU都有一些非SIMD组件。但总的来说,要充分利用GPU,您需要运行SIMD代码。
但是,你不一定写SIMD指令。即GPU SIMD是而不是与CPU SIMD相同 - 即不同于编写代码以利用x86 SSE(Stream SIMD Extensions)等。事实上,作为通过CPU SIMD给你的人之一(我很沉重参与了英特尔MMX,这是其中最早的一个,并且已经跟随FP SIMD的发展)。我经常感到有义务纠正那些认为像英特尔这样的CPU有SIMD指令的人。我更愿意考虑它们的打包矢量指令,尽管我勉强称它们为SIMD打包矢量指令集,只是因为每个人都误用了这个名称。我还强调,诸如MMX和SSE的CPU SIMD指令集可能具有SIMD打包的矢量执行单元 - 整数和浮点ALU等 - 但它们没有SIMD控制流,并且通常不具有SIMD存储器访问(又名分散/聚集(尽管英特尔Larrabee正朝着这个方向发展))。
我这个comp-arch.net维基有些(我写的计算机体系结构我的爱好): - http://semipublic.comp-arch.net/wiki/SIMD - http://semipublic.comp-arch.net/wiki/SIMD_packed_vector - http://semipublic.comp-arch.net/wiki/Difference_between_vector_and_packed_vector - http://semipublic.comp-arch.net/wiki/Single_Instruction_Multiple_Threads_(SIMT) 虽然我对尚未写过的页面道歉那就是SIMD压缩矢量指令序列,就像Intel MMX或SIMD一样。
但我不指望您阅读上述所有内容。让我试着解释一下。
试想一下,你有一段代码,看起来像这样,写在一个简单的,标量,方式时:
// operating on an array with one million 32b floating point elements A[1000000]
for i from 0 upto 999999 do
if some_condition(A[i]) then
A[i] = function1(A[i])
else
A[i] = function2(A[i])
其中功能1()和函数2()是很简单的内联 - 说函数1(x)= x * x和函数2(x)= sqrt(x)。
在CPU上。要使用像SSE这样的东西,你必须(1)将数组分成块,比如256位AVX的大小,(2)使用掩码或类似的方法自己处理IF语句。像这样:
for i from 0 upto 999999 by 8 do
register tmp256b_1 = load256b(&A[i])
register tmp256b_2 = tmp256b_1 * tmp256b_1
register tmp256b_3 = _mm_sqrt_ps(tmp256b_1) // this is an "intrinsic"
// a function, possibly inlined
// doing a Newton Raphson to evaluate sqrt.
register mask256b = ... code that arranges for you to have 32 1s in the "lane"
where some_condition is true, and 0s elsewhere...
register tmp256b_4 = (tmp256b_1 & mask) | (tmp256b_3 | ~mask);
store256b(&A[i],tmp256b_4)
你可能不认为这是如此糟糕,但请记住,这是一个简单的例子。设想多个嵌套的IF,等等。或者,想象一下“some_condition”是块状,这样你可能会节省很多不必要的计算,通过跳过部分,其中它是所有功能1或全部功能2 ...
for i from 0 upto 999999 by 8 do
register mask256b = ... code that arranges for you to have 32 1s in the "lane"
where some_condition is true, and 0s elsewhere...
register tmp256b_1 = load256b(A[i])
if mask256b == ~0 then
register tmp256b_2 = tmp256b_1 * tmp256b_1
store256b(&A[i],tmp256b_2)
else mask256b == 0 then
register tmp256b_3 = _mm_sqrt_ps(tmp256b_1) // this is an "intrinsic"
store256b(&A[i],tmp256b_3)
else
register tmp256b_1 = load256b(&A[i])
register tmp256b_2 = tmp256b_1 * tmp256b_1
register tmp256b_3 = _mm_sqrt_ps(tmp256b_1)
register tmp256b_4 = (tmp256b_1 & mask) | (tmp256b_3 | ~mask);
store256b(&A[i],tmp256b_4)
我认为你可以得到的图片?当你有多个数组时,它会变得更加复杂,有时候数据会在256位的边界上对齐,有时候不会(比如在模板计算中,你可以在所有的对齐上进行操作)。
现在,这里大概是什么样子的东西就像一个GPU:
// operating on an array with one million 32b floating point elements A[1000000]
for all i from 0 upto 999999 do
if some_condition(A) then
A = function1(A)
else
A = function2(A)
不看起来更像原来的标码?唯一真正的区别是你已经失去了数组索引,A [i]。 (实际上,一些GPGPU语言保留了数组索引,但大部分我知道不这样做)。
现在,我省略了(a)Open/CL的类C语法,(b)所有设置你需要将Open/CL代码连接到你的C或C++代码(比CUDA或OpenCL有更好的语言 - 这些代码有很多问题,但是在CPU和GPU上都有很多地方可用[**] )。但我认为我已经提出了这个问题的核心:
关于GPGPU计算的关键是你写SIMD,数据并行冷。但是,您的编写级别高于编写CPU样式的SSE代码的级别。甚至比编译器内在函数还要高。
首先,GPGPU编译器,例如OpenCL或CUDA编译器,负责处理背后的大量数据管理。编译器安排执行控制流程,tghe IF语句等。
顺便说一句,请注意,因为我用[**]标记,所以有时候所谓的SIMD GPGPU编译器可以生成可以运行的代码CPU和GPU。即SIMD编译器可以生成使用CPU SIMD指令集的代码。
但GPU本身具有特殊的硬件支持,它可以运行此SIMD代码,编译得当,比使用CPU SIMD指令在CPU上运行得快得多。最重要的是,GPU具有更多的执行单元 - 例如,象AMD Bulldoser这样的CPU有2组128位宽度的FMACS,即每周期能够执行8个FMAC。计算一个芯片上CPU的数量 - 例如8 - 每个周期可能有64个CPU。而现代GPU每周期可能有2,048 32b FMAC。即使以1/2或1/4的时钟频率运行,这也是一个很大的区别。
GPU如何有更多的硬件?那么,首先,他们通常比CPU更大的芯片。但是,他们也倾向于不花费(有些人说“浪费”)硬件,比如大型缓存和CPU花费在乱序执行上。 CPU试图快速完成一个或几个计算,而GPU并行执行许多计算,但比CPU慢得多。尽管如此,GPU每秒可以完成的计算总数远远高于CPU所能做到的。
FGPU还有其他硬件优化。例如,他们运行的线程多于CPU。而英特尔CPU每个CPU有2个超线程,给你8个CPU核心芯片上的16个线程,GPU可能有数百个。等等。
作为一名计算机架构师,我最感兴趣的是,许多GPU对SIMD控制流程都有特殊的硬件支持。与运行SSE的CPU相比,它们可以更有效地操作这些掩码。
依此类推。
无论如何,我希望我已经说的
虽然你做必须写SIMD代码为GPGPU系统(如OpenCL的)上运行。
您不应该将这类SIMD与您必须编写以利用Intel SSE的SIMD代码混淆。
它更干净。
越来越多的编译器允许相同的代码在DCPU和GPU上运行。即他们越来越支持干净的“真正的SIMD”编码风格,而不是像现在一直利用MMX和SSE和AVX一样必需的假“伪SIMD”编码风格。这很好 - 这样的代码在CPU和GPU上编程同样“好”。但GPU经常运行得更快。英特尔有一篇名为“揭开100X GPU与CPU神话:对CPU和GPU吞吐量计算的评价”的文章,http://www.hwsw.hu/kepek/hirek/2010/06/p451-lee.pdf。它表示GPU“平均只有”2.5倍的速度。但是,这是经过大量积极的优化。 GPU代码通常更容易编写。我不了解你,但我认为“只有”2.5倍的速度并没有太大的打喷嚏。特别是因为GPGPU代码通常更容易阅读。
现在,没有免费的午餐。如果你的代码自然是数据并行的,那么很好。但一些coede不是。这可能是一个痛苦。与所有机器一样,GPU也有其怪癖。但是如果你的代码自然是数据并行的,那么你可能会获得很好的加速,代码更具可读性。
我是一名CPU设计师。我期望从GPU中借鉴很多想法,让雄性CPU运行得更快,反之亦然。
- 1. 是MonetDB使用SIMD指令
- 2. 不是允许执行存储过程
- 3. 是否Numbapro支持SIMD编程架构
- 4. 允许onclick函数只执行一次
- 5. 只允许某个UIGestureRecognizer一次执行
- 6. pthread_join()是否允许执行调用线程继续?
- 7. 编译汇编程序与SIMD指令和c#集成
- 8. 允许PHP执行linux命令
- 9. 允许iframe执行cordova命令
- 10. ColdFusion jnbridge许可证是否允许(命令行)使用jnbproxy?
- 11. 限制为“允许”指令
- 12. 是否存在允许执行命令行的Mercurial的GitX等价物?
- 13. Primefaces datatable roweditor:只允许一行编辑
- 14. 一个汇编程序指令是否总是以原子方式执行?
- 15. gimp是否允许您设置指南?
- 16. 从SIMD指令捕获SIGFPE
- 17. Qt Creator中的SIMD指令
- 18. SIMD视频指令CUDA
- 19. 调度SIMD指令+ SIMDPP + qmake
- 20. 通过WAMP执行GPGPU程序
- 21. SIMD编程
- 22. 指令/指令是在运行时还是汇编时执行的?
- 23. 此编译器转换是否允许?
- 24. 允许使用execvp执行程序
- 25. 指令应该只执行一次
- 26. iPhone:知道编程是cookie被允许或不允许
- 27. 任务API 2.0是否允许执行launch.json中的条目
- 28. 骡3:控制流是否被允许执行
- 29. Java:JTable只允许100行
- 30. 是否有支持GPGPU编程的视频卡的列表?