超音波流体屋のプログラム備忘録

CULA Dense (R17, CUDA 5.5)

最終更新:

usapfrog

- view
管理者のみ編集可
(CUDA 5.5, CULA Dense R17 版の情報です。)

アカデミックならFull Editionが使える。
ダウンロードは以下からID登録してから。
http://www.culatools.com/downloads/dense/
linuxは落としてきた.runを管理者権限でbashで実行。

ソース

R14の時のcutilが使えなくなったので、そのへんを修正。
参考:
CUDA5.5+Fedora19
CUDA™ 5.5 開発環境をインストールする (Linux版)

CULA使い方の一例として、連立方程式 Ax = bを解く話。
んで今回はMatlab記法で A=ones(10 000, 10 000)-eye(10 000); b=ones(10 000, 1);
対角成分だけ0、後は1の行列。解は確か全部 1/9999。

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3.  
  4. #include <cuda_runtime.h>
  5. #include <helper_functions.h>
  6. #include <helper_cuda.h>
  7. #include <cula.h>
  8.  
  9.  
  10. int main(int argc, char** argv){
  11.  
  12. int devID = findCudaDevice(argc, (const char **)argv);
  13. culaStatus s; //失敗するとculaNoError以外が入るらしい
  14. s = culaInitialize();
  15.  
  16. //ホスト領域の確保・値の代入
  17. double *a, *b;
  18. int n=10000;
  19. int m=10000;
  20. a = (double *)calloc(sizeof(float), m*n);
  21. b = (double *)calloc(sizeof(float), m);
  22. //やってみたらいわゆるColumn-major, CLapackと同じらしい
  23. int i, j;
  24. for(i=0; i<n; i++){
  25. for(j=0; j<m; j++){
  26. a[i+j*n]= (double) (i != j);
  27. }
  28. b[i] = 1;
  29. }
  30. //その他、行数・列数情報。CLapackと同じ。
  31. int ipiv[n];
  32. int nrhs = 1;
  33. int lda = n;
  34. int ldb = n;
  35.  
  36. //実行・タイマー測定
  37. StopWatchInterface *timer = 0;
  38. sdkCreateTimer(&timer);
  39. sdkStartTimer(&timer);
  40.  
  41. //連立方程式を解く。これ1行。
  42. s = culaDgesv(n, nrhs, a, lda, ipiv, b, ldb);
  43.  
  44. //タイマーストップ
  45. sdkStopTimer(&timer);
  46. printf("計算時間 =%f(ms)\n", sdkGetTimerValue(&timer));
  47. sdkDeleteTimer(&timer);
  48.  
  49. //エラー処理等したければ。 正常終了なら0が返る。
  50. printf("culastate %d noerr:%d \n", s, culaNoError);
  51.  
  52. //結果表示
  53. for(j=0; j<m; j++) {
  54. if( j % 1000 == 0) printf("%f ", b[j]);
  55. }
  56.  
  57. //終了処理
  58. free(a);
  59. free(b);
  60. culaShutdown();
  61. return 0;
  62. }
  63.  

環境変数

.bashrcあたりに以下の記述を突っ込んどく
  1. export CUDA_ROOT=/usr/local/cuda-5.5
  2. export CULA_ROOT=/usr/local/cula
  3. export CULA_INC_PATH=$CULA_ROOT/include
  4. export CULA_LIB_PATH_64=$CULA_ROOT/lib64
  5. export CUDA_INCPATH=$CUDA_ROOT/include:$CUDA_ROOT/samples/common/inc:$CULA_INC_PATH
  6.  
  7. export PATH=$CUDA_ROOT/bin:$PATH
  8. export LD_LIBRARY_PATH=$CUDA_ROOT/lib64:$CULA_LIB_PATH_64:$LD_LIBRARY_PATH
  9. export LIBRARY_PATH=$LD_LIBRARY_PATH
  10. export C_INCLUDE_PATH=$CUDA_INCPATH:$C_INCLUDE_PATH
  11. export CPLUS_INCLUDE_PATH=$CUDA_INCPATH:$CPLUS_INCLUDE_PATH
  12.  


コンパイル

Nsightが便利なので、そっちを使いましょう。
CULAのライブラリの登録だけ必要。プロジェクト右クリックで、
Properties → Build → Settings
Tool Settingsタブ → NVCC Linker → Libraries
Addのアイコン → でてきたダイアログに cula_lapack

Makefileならこんな感じ。
  1. CC=nvcc
  2. ARCH=-arch=sm_13
  3. LIB=-lcula_lapack
  4. SRC=sample.cu
  5. OUT=sample.out
  6. all:
  7. ${CC} ${ARCH} ${SRC} -o ${OUT} ${LIB}
  8.  

計算時間

Nvidia Tesla K20 で 1.8秒。
倍精度なので値も正確。

あらかじめGPUに格納しときたいときは

culaDeviceSgesvほかdevice系の関数を使う。
行列Aとベクトルbに対応する領域、加えて関数に必要な配列ipivなども忘れずにデバイス上に確保してから、
同様の関数を採用すればよい。上記42行付近は以下の通りに書き換える。
  1. {
  2. double *da, *db;
  3. int *dipiv;
  4. cudaMalloc((void**) &da, sizeof(double)*n*n);
  5. cudaMalloc((void**) &db, sizeof(double)*n);
  6. cudaMalloc((void**) &dipiv, sizeof(int)*n);
  7.  
  8. cudaMemcpy(da, a, sizeof(double)*n*n, cudaMemcpyHostToDevice);
  9. cudaMemcpy(db, b, sizeof(double)*n, cudaMemcpyHostToDevice);
  10.  
  11. s = culaDeviceDgesv(n, nrhs, da, lda, dipiv, db, ldb);
  12. }
  13.  


目安箱バナー