您的位置:首页 > 运维架构 > Linux

CUDA程序优化心得之测时函数的设计

2010-05-13 21:09 309 查看
近一年来,学习CUDA也算是有苦有甜,苦的是遇到问题时的无助、苦恼和迷茫,甜的是问题解决时的兴奋,今天就利用这五一的假期把自己的经验结合CUDA优化的内容写下来,希望对于那些依旧在其中挣扎的同学有所帮助。

一、        测时
判断程序优劣的最简单方式就是计算程序的运行时间,在同一台机器上,运行时间短的程序一般来说是更优的,当然不能一概而论,毕竟决定程序运行速度的因素很多,比如算法,机器的指令集,使用的语言等等。
        我们的目的是要设计一个既能够在windows上运行,又能够在linux上运行,既可以用于C,又可以用于CUDA的计时器,同时最好便于扩展。计时的方法很多,如标准C库的time、clock系列函数,CUDA的事件,linux下的gettimeofday,windows下的GetTickCount。
        本计时器系列采用C++的面向对象设计方法,基本的思路是设计一个父类,然后再从父类创造子类。这样要建造一个新计时器,只要继承父类就行了。
        父类代码如下:

[Copy to clipboard] [ - ]
CODE:
        class TimeCounter{
                protected :
                        clock_t startp,endp;
                public :
                        TimeCounter():startp(-1),endp(-1){}
                        void start(){//设置计时起点
                        #ifdef __CUDACC__
                                cudaThreadSynchronize();
                        #endif
                                startp=clock();
                        }
                        void stop(){//设置计时终点
                                if(-1==startp){
                                        perror("you must set start point at first");
                                }else{
                                #ifdef __CUDACC__
                                        cudaThreadSynchronize();
                                #endif
                                        endp=clock();
                                }
                        }
                        virtual long getTimeDiff()=0;//返回时间差滴答数
                        virtual void printTimeDiff()=0;//打印出时间差
        };

子类秒计时器代码如下:

[Copy to clipboard] [ - ]
CODE:
        class SecondCounter:public TimeCounter{
                public :
                    long getTimeDiff(){
                                 if(-1==endp){
                                        perror("you must set stop point before invoke this function");
                                        exit(1);
                                }else{
                                        return (endp-startp)/CLOCKS_PER_SEC;
                                }
                        }
                        void printTimeDiff(){
                                long temp=getTimeDiff();
                                printf("use time :%lds/n",temp);
                        }
        };

子类毫秒计时器代码如下:

[Copy to clipboard] [ - ]
CODE:
        class MillisecondCounter:public TimeCounter{
                public :
                    long getTimeDiff(){

                                 if(-1==endp){
                                        perror("you must set stop point before invoke this function");
                                        exit(1);
                                }else{
                                        return 1.0f*(endp-startp)/CLOCKS_PER_SEC*1000;
                                }
                        }
                        void printTimeDiff(){
                                long temp=getTimeDiff();
                                printf("use time :%ldms/n",temp);
                        }
        };

子类微秒计时器代码如下:

[Copy to clipboard] [ - ]
CODE:
#ifdef __CUDACC__
class MicrosecondCounter:public TimeCounter{
                public:
                        long getTimeDiff(){
                                if(-1==endp){
                                        printf("please set start point or end point/n");
                                        exit(1);
                                }else{
                                return 1.0f*(endp-startp)/CLOCKS_PER_SEC*1000000;
                                }
                        }
                        void printTimeDiff(){
                                long temp=getTimeDiff();
                                printf("use time:%ld us/n",temp);
                        }
        };
#endif

这种设计使得我们可以声明一个计时器父类引用,而让其实际指向子类,这样,如果精度小了的话,就可以只更改一处,而不用更改其它的内容了。在我的实践中,这种基于对象的多态设计的计时器工作得很好。在开始计时处调用start方法,在计时终点调用stop方法,调用getTimeDiff方法返回经过的时间数,但是这个方法有个问题就是如果两个不同的子类的计时器,其用此函数获得的值不能直接相加减,由于这个问题我本来想将其设置private,但是最终还是让其保持public,因为这符合C/C++的设计思想:程序员是最聪明的,他们应当知道会发生什么,一切由他们来决定。函数printTimeDiff打印计时时间。
        如果有一天C语言的clock函数精度达到了微秒,我们只用将包围MicrosecondCounter类的条件编译语句去掉就行了。如果有一天其精度达到了纳秒,我们只用再写一个类继承TimeCounter类就行了,不用改写任何代码。

 

 

int main(int argc,char *argv[]){

    MicrosecondCounter mc;
    TimeCounter& tc = mc;
   
    tc.start();
   
    int a = 0;
    for(int i = 0; i < 10000000; i++){
        a += 5;
    }
    tc.stop();
   
    tc.printTimeDiff();

        return 0;

}

 

转自:http://cuda.itpub.net/thread-1299171-1-2.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息