system
2012 年11 月 21 日 02:14
1
GPU:Tesla C2050
问题 :我的CUDA程序在启动时有很长的长达若干秒(7~8s左右)的耗时,请问这部分耗时是因为什么。我并没有显示地对设备进行选择或其他设置,是否是这部分Device初始化的时间费时间?这部分时间是不是无法减少?
计时 :
我是在一个Fortran程序里调用了一个C的转接函数,在这个C函数里面又调用了Kernel函数。在这个C转接函数内部的首尾计时发现只用了30毫秒(用cudaEvent计时,包含了cudaMemcpy),在调用这个C函数的前一行和后一行计时,却发现耗费了7s~8s左右。
//fortran program
time stamp : t1
CALL C function ()
time stamp : t2
//the C function
void function ()
{
time stamp : t3
MALLOC();
MEMCPY();
time stamp: t4
kernel<<<…>>>();
time stamp:t5
MEMCPY();
time stamp: t6
}
t1-t2用时7秒左右,t3-t6用时30毫秒左右,t4-t5用时不到10毫秒。
system
2012 年11 月 21 日 02:35
2
不清楚这个是fortran转接c造成的,还是device热身造成的,还是其他什么。
不过,你可以这样,写一个空的kernel,在这一段前面调用一下,然后再调用本段,让空的kernel完成热身。然后再看各段计时有什么变化。这或许有助于帮助我们判断问题所在。
欢迎莅临论坛,祝您编码愉快。
system
2012 年11 月 21 日 02:56
3
谢谢欢迎和建议~
我用C的time.h里的time()重新在各重要位置记了一下时间,计时结束点均在程序末尾,如果计时开始点在第一条CUDA语句(不包括变量声明,在我的程序里是cudaEventCreate)之后,那么返回的时间就费少小,毫秒级,如果计时开始点在第一条CUDA语句之前,那么返回的时间就是8s,很长。
按照这个观察,我认为初始化应该是在执行第一条CUDA代码之前隐式地进行的,不是在kernel执行前,而且很费时。
有朋友说不同系列的device,初始化时间不一样,GTX系列就很好,TESLA的CXXXX貌似初始化就很费时,我的就是C2050。不知道有没有别的同仁遇到此类问题。
system
2012 年11 月 21 日 03:04
4
runtime API的初始化确实是自动的,隐式的,在您第一次调用kernel或者调用runtime API函数的时候,自动完成。
不过初始化需要多少时间我倒没有详细关注过,建议您再研究一下。
以及如果实在无法缩短此时间,那么可以考虑尽可能在最靠前的地方调用空的kernel一次,用后面host端的执行时间对该时间进行掩盖。
如果可以跑profiler的话,也可以看看前面的延迟情况。
祝您编码愉快~
system
2012 年11 月 21 日 03:26
5
谢谢!
这部分时间我去查查资料吧,看看能不能改善,或者在别的设备上能好一些。
system
2012 年11 月 21 日 03:35
6
问题应该不是DEVICE初始化,DEVICE初始化非常快,不会出现7-8s的情况。楼主可以尝试直接用FORTRAN写内核并调用再测时间试试。
system
2012 年11 月 21 日 04:05
7
7-8秒? 这个不是设备初始化/模块/kernel热身,因为没有那么长(同时你也应该能看出来,这些时间都算在t3-t6里,如果你之前没有调用过cuda的函数的话,才多少?一共才0.03秒。)
可能是你的fortran调用C导致的。但具体情况尚不清楚。
提供一个参考:我用C#调用C(CUDA), 没有发现这么长。这个7-8秒太离谱了。很奇怪。
你可以在t1和t2之间换成空C函数看看,是否是fortran调用C的自身问题。
system
2012 年11 月 21 日 11:20
8
Fortran调用C我做过实验,没有感到有明显额外费时,速度很快。1#里面的t3-t6是我用cudaEvent统计的,而费时7s的地方在cudaEventCreate之前,所以t3-t6的时间是正常的。
见3#,cudaEventCreate之前应该是被编译器隐式地加入了代码。
我在GTX上跑CUDA时也没有经历如此长的时间,所以这个感觉很奇怪。
谢谢建议!
system
2012 年11 月 21 日 11:22
9
一开始我是准备用Fortran写的,但是PGI的CUDA Fortran编译器无法和原有的Fortran在同一个project里面混用,具体就是一种Fortran编译出的module文件无法被别的Fortran编译器使用,而且老板买的CUDA Fortran到期了,索性就改用CUDA C了,还能5.0,将来方便转Kepler。
我怀疑是不是在2.0计算能力的卡上面跑5.0的驱动造成的。
谢谢建议!
system
2012 年11 月 21 日 12:08
10
可能是驱动初始化,但的确在C2050上从来没遇过这么长时间的情况。你可以试试将驱动设成persistent mode(第一次初始化后再运行cuda代码就不用初始化了)
nvidia-smi -pm 1
system
2012 年11 月 21 日 14:18
11
额!亲!!
你不能这么测试,你需要用和被测试对象无关的代码来测试。
您用event来测试,实际上在您创建event的时候,cuda已经隐式的初始化了!!所以此时间你测不到!
您可以使用QueryPerformanceCounter/Frequency(), 他们和cuda runtime无关,不会干扰。
system
2012 年11 月 21 日 14:22
12
只有如此,您才能知道是否真的您是因为cuda runtime的隐式初始化(包括context建立,模块载入,函数查找等等)而占用的时间。
system
2012 年11 月 21 日 14:27
13
居然没看到此楼!!善哉。用time是可以的,当不需要测试很短暂的时间的时候。您这么测试,的确表明是初始化占用了8s的时间。这的确是问题的所在。
但是很奇怪。理论不会这么长。初始化没多少东西可干,8s的确离谱了。
这个初始化是指的runtime api的。至于驱动的初始化,这个我不懂。建议看下WangPeng楼层。看看是否有效。
system
2012 年11 月 21 日 14:31
14
我搜索了下,的确WP说的有可能:看这个例子:
time ./cuda_test
real 0m5.650s
user 0m0.002s
sys 0m5.500s
nvidia-smi -pm 1
time ./cuda_test
real 0m0.374s
user 0m0.006s
sys 0m0.367s
system
2012 年11 月 26 日 07:41
16
我搜索了下,的确WP说的有可能:看这个例子:
time ./cuda_test
real 0m5.650s
感谢建议!!!
我现在确定是这部分耗时,因为我需要设置flag,而设置flag必须要reset,所以耗时。
checkCudaErrors(cudaSetDevice(3));
checkCudaErrors(cudaDeviceReset());
checkCudaErrors(cudaSetDeviceFlags(cudaDeviceScheduleBlockingSync));
以前我把这部分放到循环里面了,所以每次都reset,耗时就很恐怖,现在发现我2了,我把这部分现在放到主程序一开始,就只需要reset一次了。
从循环里面拿出去以后,就只在程序启动时有一次7s左右的耗时了,因为我的程序很长,跑起来要几个小时,所以这1个7s完全可以接受~
system
2012 年11 月 26 日 07:41
17
谢谢!
见楼上回复,问题应该是解决了,是Reset费时
system
2012 年11 月 26 日 08:05
18
恭喜恭喜,感谢您回馈结果,造福论坛!
欢迎多常来看看。
祝您编码愉快~