CUDA程式優化心得之錯誤處理

yyfn風辰發表於2010-05-14
標準C提供了錯誤輸出函式perror,其功能是將在呼叫其處最近之前出錯的錯誤輸出到的標準錯誤流,當然利用作業系統的功能,你也可以將它們重定向到檔案。
由於CUDA函式設計為都返回錯誤碼,而且CUDA本身也提供了兩個函式cudaGetLastError和cudaGetErrorString,因此其處理可充分利用這兩個函式,另外我們在寫CUDA程式時,經常要驗證結果和CPU上的結果是否一致,因此我也提供了這個功能。
程式程式碼如下:
class ErrorHander{//file:file name;line:lineNo
        const static float EPSFLOAT = 0.000001;
        const static double EPSDOUBLE = 0.0000000001;
        public :
#ifdef __CUDACC__
        //can't use it at asynchronize situation
                void static printError(cudaError_t cet){
                        if(cudaSuccess != cet){
                                printf("error:%s\n",cudaGetErrorString(cet));
                                fflush(stdout);
                                exit(1);
                        }
                }
        //can use it at anywhere
                void static printLastError(){
                        cudaThreadSynchronize();
                        cudaError_t cet = cudaGetLastError();
                        if(cudaSuccess != cet){
                                printf("error:%s!\n",cudaGetErrorString(cet));
                                fflush(stdout);
                                exit(1);
                        }
                }
                void static printError(int line,cudaError_t cet){
                        if(cudaSuccess !=cet){
                                printf("line:%d,error:%s\n",line,cudaGetErrorString(cet));
                                fflush(stdout);
                                exit(1);
                        }
                }
                void static printLastError(int line){
                        cudaThreadSynchronize();
                        cudaError_t cet = cudaGetLastError();
                        if(cudaSuccess != cet){
                                printf("line:%d,error:%s!\n",line,cudaGetErrorString(cet));
                                fflush(stdout);
                                exit(1);
                        }
                }
                void static printError(char *file,int line,cudaError_t cet){
                        if(cudaSuccess != cet){
                                printf("%s,line:%d,error:%s\n",file,line,cudaGetErrorString(cet));
                                fflush(stdout);
                                exit(1);
                        }
                }
                void static printLastError(char *file,int line){
                        cudaThreadSynchronize();
                        cudaError_t cet = cudaGetLastError();
                        if(cudaSuccess != cet){
                                printf("%s,line:%d,error:%s!\n",file,line,cudaGetErrorString(cet));
                                fflush(stdout);
                                exit(1);
                        }
                }
#endif
                void static valid(const int *first,const int *second, int num, int firstSpan = 1,
                                int secondSpan = 1, int firstOffset = 0, int secondOffset = 0){
                        for(int i=0;i                                 assert(first[firstOffset+i*firstSpan]==second[secondOffset+i*secondSpan]);
                        }
                }
                void static valid(const float *first, const float *second, int num, int firstSpan = 1,
                        int secondSpan = 1, int firstOffset = 0, int secondOffset = 0){
                        for(int i=0;i         assert(abs(1-(first[firstOffset + i*firstSpan]/second[secondOffset+i*secondSpan]))         }
                         }
                        void static valid(const double *first, const double *second, int num, int firstSpan = 1,
                             int secondSpan = 1, int firstOffset = 0, int secondOffset = 0){
                             for(int i=0;i         assert(abs(1-(first[firstOffset + i*firstSpan]/second[secondOffset+i*secondSpan]))                      }
                 }
};
printError函式列印傳入的cuda函式返回的錯誤碼所代表的錯誤,printLastError列印最後一次錯誤的錯誤字串。file代表檔名,呼叫時可用__FILE__巨集代替,line代表行數,呼叫時可傳入__LINE__巨集,當然由於設計上的缺陷,你也可以傳入其它的資訊。valid函式用於確定兩個陣列的資料是不是一樣的,本來想使用模板,但是還是使用了過載。由於全部採用靜態函式,所以我們沒有必要建立物件,直接使用類名呼叫就行了,這樣可以方便的使用條件編譯來啟用/關閉除錯資訊,這一點比cutil庫的cudaSafeCall好用得多。另外這個類的功能也足夠使用了。如果你想改變精度限的話,改變EPS變數的值就可以了。非常的方便。
        另,由於能力所限或者說設計缺陷,printError各函式都無法處理非同步呼叫錯誤。另外這些工具函式只是拿來除錯用的,真正的出錯處理不能這樣做。
        當然我個人的庫包含的類遠比這要多,比如還有檔案輸入輸出,隨機數初始化等。這些內部就不包括在本節了。
        整體而言,這兩節都是一些準備工作。從下一節起才真正涉及到優化的內容。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/23057064/viewspace-662699/,如需轉載,請註明出處,否則將追究法律責任。

相關文章