我正在尝试评估一个简单的cuda fortran代码的加速:数组的增量。
CPU版本:
module simpleOps_m
contains
subroutine increment (a, b)
implicit none
integer , intent ( inout ) :: a(:)
integer , intent (in) :: b
integer :: i, n
n = size (a)
do i = 1, n
a(i) = a(i)+b
enddo
end subroutine increment
end module simpleOps_m
program incrementTest
use simpleOps_m
implicit none
integer , parameter :: n = 1024*1024*100
integer :: a(n), b
a = 1
b = 3
call increment (a, b)
if ( any(a /= 4)) then
write (* ,*) '**** Program Failed **** '
else
write (* ,*) 'Program Passed '
endif
end program incrementTest
GPU版本:
module simpleOps_m
contains
attributes ( global ) subroutine increment (a, b)
implicit none
integer , intent ( inout ) :: a(:)
integer , value :: b
integer :: i, n
n = size (a)
do i=blockDim %x*( blockIdx %x -1) + threadIdx %x ,n, BlockDim %x* GridDim %x
a(i) = a(i)+b
end do
end subroutine increment
end module simpleOps_m
program incrementTest
use cudafor
use simpleOps_m
implicit none
integer , parameter :: n = 1024*1024*100
integer :: a(n), b
integer , device :: a_d(n)
integer :: tPB = 256
a = 1
b = 3
a_d = a
call increment <<< 128,tPB >>>(a_d , b)
a = a_d
if ( any(a /= 4)) then
write (* ,*) '**** Program Failed **** '
else
write (* ,*) 'Program Passed '
endif
end program incrementTest
所以我用pgf90编译了两个版本 http://www.pgroup.com/resources/cudafortran.htm
使用“time”命令评估执行时间,我得到:
表示CPU版本
$ time(cpu executable)
真实0m0.715s
用户0m0.410s
sys 0m0.300s
for GPU version
$ time(gpu可执行文件)
真实的0m1.057s
用户0m0.710s
sys 0m0.340s
因此加速=(CPU exec.time)/(GPU exec.time)是&lt; 1 有什么理由说明为什么加速不是> 1应该达到什么?
提前致谢
答案 0 :(得分:1)
这里的问题是,在这个相当人为的例子中,初始化主机上的大型数组(a=1
)的成本几乎与增加数组内容的循环成本相同,这是部分在GPU上并行化的代码。由于并行工作的总量与串行工作的总量大致相同,因此Amdahl's Law通过并行化GPU上的某些代码来实现任何显着的加速,从而大量堆叠。
通过将初始化和增量操作融合到GPU上的单个并行操作中,可以实现更显着的加速。
[这个答案已经从评论中汇总而成,并作为社区维基条目添加,以便将这个问题从CUDA标签的未答复列表中删除]