青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

C++ Coder

HCP高性能計算架構,實現,編譯器指令優化,算法優化, LLVM CLANG OpenCL CUDA OpenACC C++AMP OpenMP MPI

C++博客 首頁 新隨筆 聯系 聚合 管理
  98 Posts :: 0 Stories :: 0 Comments :: 0 Trackbacks
http://blog.csdn.net/bendanban/article/details/7674674

一步步做程序優化【1】講一個用于OpenACC優化的程序

很經典的例子,矩陣的乘法。呵呵。。。

分析下A,B,C為三個矩陣,A為m*n維,B為n*k維,C為m*k維,用A和B來計算C,計算方法是:C = alpha*A*B + beta*C。它的程序如下:

// C = alpha*A*B + beta*C
void mySgemm(int m, int n, int k, float alpha, float beta,\
             
float *A,  float *B, float *
C)
{
    
int
 i, j, l;
    
float
 ab;
    
for(j = 0; j < m; j++

    
{
        
for(i = 0 ;i < k ;i++
)
        
{
            ab 
= 0.0f
;
            
for(l = 0 ;l < n ;l++
)
            
{
                ab 
+= A[j*n+l] * B[l*k+
i];
            }

            C[j
*k+i] = alpha*ab + beta*C[j*k+i];
        }

    }

}

 

這個程序修改自HMPP_Tutorial_Labs_CUDA中的lab0。

C中的每個元素的計算是獨立的,完全可以并行化。后面的系列文章將會講述優化這個程序的整個過程。

一步步做程序優化【2】OpenACC指令

這個寫了很長時間了,但是一直沒有顧上額。把這個版本稍微修改一下,只需要加上一個指令,我們就可以得到不錯的效率奧。

看代碼吧:

// C = alpha*A*B + beta*C
void mySgemm(int m, int n, int k, float alpha, float beta,\
             
float *A,  float *B, float *C)
{
    
int i, j, l;
    
float ab;
#pragma acc kernels copy(A[
0:m*n],B[0:m*n],C[0:m*n])
#pragma acc loop independent
    
for(j = 0; j < m; j++
    {
#pragma acc loop independent
        
for(i = 0 ;i < k ;i++)
        {
            ab 
= 0.0f;
            
for(l = 0 ;l < n ;l++)
            {
                ab 
+= A[j*n+l] * B[l*k+i];
            }
            C[j
*k+i] = alpha*ab + beta*C[j*k+i];
        }
    }
}

 

這樣,我們只是加入了幾個指導語句,剩下的事是編譯器幫我們做的奧,你原先的測試程序并不需要任何改變奧。

我之前講過HMPP編譯器的安裝和使用,http://blog.csdn.net/bendanban/article/details/7662583大家可以使用HMPP編譯器編譯這段代碼,在Linux下(安裝好CUDA,HMPP之后)我們可以使用一下命令編譯:

$hmpp --codelet-required gcc your_program.c

執行一下,你會發現速度相當的快了(你要有支持CUDA的顯卡才行奧)

大家可以寫一個測試程序來調用這個函數,隨便你用什么編譯器,只要你可以在你的測試程序里找到本文中提供的程序,你完全可以使用高效的函數奧。

 

為了得到更高的效率,我修改一下這個代碼:

// C = alpha*A*B + beta*C
void mySgemm(int m, int n, int k, float alpha, float beta,\
             
float *A,  float *B, float *C)
{
    
int i, j, l;
    
float ab;
#pragma acc kernels copyin(A[
0:m*n],B[0:m*n]) copy(C[0:m*n])
#pragma acc loop independent
    
for(j = 0; j < m; j++
    {
#pragma acc loop independent
        
for(i = 0 ;i < k ;i++)
        {
            ab 
= 0.0f;
            
for(l = 0 ;l < n ;l++)
            {
                ab 
+= A[j*n+l] * B[l*k+i];
            }
            C[j
*k+i] = alpha*ab + beta*C[j*k+i];
        }
    }
}

 

這樣A和B兩個矩陣就可只是傳輸到GPU上,而C傳到GPU,計算結束后會倍傳回來。

在copy()中,A[0:m*n],表示從第0個元素一共計算m*n個元素,第一個是起始位置,第二個量表示數據長度。

大家把代碼拷貝走,去試試吧?。。?br />

一步步做程序優化【3】OpenHMPP指令(更加靈活的使用異構計算)

1、簡介下HMPP

HMPP指的是(Hybrid Multicore Parallel Programming),他是由CAPS(http://www.caps-entreprise.com(英文);www.caps-entreprise.com.cn(中文))  發起的一種異構計算的標準,他的出現可以大大減少我們的程序優化時間。大家可以參考我之前的幾篇講解HMPP的文章去獲得HMPP的試用版

HMPP是一種基于編譯指導語句(類似與OpenMP)的標準,它與OpenMP的區別是:OMP是基于CPU的并行標準,HMPP是基于異構平臺的標準(例如CPU+GPU,CPU+MIC),它支持C和Fortran兩種語言。

另外HMPP編譯器可以根據你的#pragma指令產生CUDA代碼,也可以直接編譯CUDA代碼!

總之,HMPP編譯器非常強大!微笑

2、使用HMPP以及OpenACC的一個推薦原則。

使用HMPP是為了盡可能不改變原有代碼的基礎上只需要添加少量的#pragma 語句就可一獲得幾十甚至幾千倍的加速比。當然前提是你原有的代碼要可以正確的按照算法設計的目的執行才行。


3、繼續優化矩陣相乘的那段代碼

1)重新貼一邊需要優化的代碼:(特別注意這段代碼來值CAPS,這是原始代碼,我沒有做實質性的修改)

 

/* 
 * Copyright 2008 - 2012 CAPS entreprise. All rights reserved.
 
*/



#include 
<getopt.h>
#include 
<sys/time.h>
#include 
<stdlib.h>
#include 
<stdio.h>
#include 
<string.h>
#include 
<math.h>

// Number of execution
#define NB_RUNS 5

// Size of the matrix
#define SIZE 256

// Initialization random value
#define SRAND_VALUE 5347

// Use to initialize the matrix
float randFloat(float low, float high)
{
  
float t = (float)rand() / (float)RAND_MAX;
  
return (1.0f - t) * low + t * high;
}


////////////////////////////////////////////////////////////////////////////////
// sgemm_codelet
////////////////////////////////////////////////////////////////////////////////
void mySgemm( int m, int n, int k, float alpha, float beta,
                
float a[m][n],   float b[n][k], float c[m][k] )
{
  
int i,j,l; // Induction variables
  float ab;  // Temporary result 

  
for( j = 0 ; j < m ; j++ ) {
    
for( i = 0 ; i < k ; i++ ) {
      ab
=0.0f;
      
for( l = 0 ; l < n ; l++ ){
        ab 
+= a[j][l] * b[l][i];
      }

      c[j][i] 
= alpha * ab + beta * c[j][i];
    }

  }

}



////////////////////////////////////////////////////////////////////////////////
// Main program
////////////////////////////////////////////////////////////////////////////////
int main(int argc, char **argv)
{

  
int m=SIZE, n=SIZE, k = SIZE;

  
float *my_a=NULL, *b=NULL, *c_hwa=NULL, *c_cpu=NULL;
  
int i, j, ii;
  
// For timer measures
  struct timeval tv_global_begin, tv_global_end; // global timer (all iterations)
  struct timeval tv_begin, tv_end;  // local timer (1 iteration)

  unsigned 
long long int best_measure_GPU = 0;
  unsigned 
long long int sum_measure_GPU  = 0;

  unsigned 
long long int best_measure_CPU = 0;
  unsigned 
long long int sum_measure_CPU  = 0;

  unsigned 
long long int global_CPU_time  = 0;
  unsigned 
long long int global_GPU_time  = 0;

  unsigned 
long long int current;

  
float alpha, beta;

  
double error    = 0.0;
  
int index_i     = 0.0;
  
int index_j     = 0.0;
  
double valueCPU = 0.0;
  
double valueGPU = 0.0;



  
// Allocating CPU memory
  my_a = (float *)malloc(m* n * sizeof(float));
  my_b 
= (float *)malloc(n * k * sizeof(float));
  c_hwa 
= (float *)malloc(m * k * sizeof(float));
  c_cpu 
= (float *)malloc(m * k * sizeof(float));

  
if((my_a == NULL) || (my_b == NULL) || (c_hwa == NULL) || (c_cpu == NULL)) {
    fprintf( stderr, 
"\n**** error : memory allocation failed ****\n\n");
    
return 1;
  }


  fprintf( stdout, 
"---- Initialization of the Matrices ----\n\n");
  srand(SRAND_VALUE);

  
//Generate options set

  
for(i = 0; i < m; i++){
    
for(j = 0; j < n; j++){
      my_a[i
*n+j] = randFloat(0.0001f1.0f);
    }

  }



  
for(i = 0; i < n; i++){
    
for(j = 0; j < k; j++){
      my_b[i
*k+j] = randFloat(0.0001f1.0f);
    }

  }



  
for(i = 0; i < m; i++){
    
for(j = 0; j < k; j++{
      c_cpu[i
*k+j] = randFloat(1.020.0f);
      c_hwa[i
*k+j] = c_cpu[i*k+j];
    }

  }


  alpha 
= 0.5;
  beta  
= randFloat(1.02.0);

  fprintf( stdout, 
"---- Running calculations ----\n");


  
// run sgemm on GPU (NB_RUNS iterations)
  printf("Run on GPU\n");

  
// Start timer
  gettimeofday(&tv_global_begin, NULL);


  
for( i=0; i<NB_RUNS; i++ ) {
    printf(
"%d ",i);
    gettimeofday(
&tv_begin, NULL);

    mySgemm( m, n, k, alpha, beta, my_a, my_b, c_hwa );
    gettimeofday(
&tv_end, NULL);

    current 
= (tv_end.tv_sec-tv_begin.tv_sec)*1e6 + tv_end.tv_usec-tv_begin.tv_usec;

    
if( ( best_measure_GPU == 0 ) || ( best_measure_GPU > current ) ){
      best_measure_GPU 
= current;
    }

    sum_measure_GPU 
+= current;
  }




  gettimeofday(
&tv_global_end, NULL);
  global_GPU_time 
= (tv_global_end.tv_sec-tv_global_begin.tv_sec)*1e6 + tv_global_end.tv_usec-tv_global_begin.tv_usec;
  
// run sgemm on CPU (NB_RUNS iterations)
  printf("\n\nRun on CPU\n");

  
// Start timer
  gettimeofday(&tv_global_begin, NULL);

  
for( i=0; i<NB_RUNS; i++ ) {
    printf(
"%d ",i);
    gettimeofday(
&tv_begin, NULL);

    mySgemm( m, n, k, alpha, beta, my_a, my_b, c_cpu );

    gettimeofday(
&tv_end, NULL);
    current 
= (tv_end.tv_sec-tv_begin.tv_sec)*1e6 + tv_end.tv_usec-tv_begin.tv_usec;

    
if( ( best_measure_CPU == 0 ) || ( best_measure_CPU > current ) ){
         best_measure_CPU 
= current;
    }

    sum_measure_CPU 
+= current;
  }


  gettimeofday(
&tv_global_end, NULL);
  global_CPU_time 
= (tv_global_end.tv_sec-tv_global_begin.tv_sec)*1e6 + tv_global_end.tv_usec-tv_global_begin.tv_usec;


  
// Compute error between GPU and CPU    
  for( ii = 0; ii < m; ii++){
    
for(j = 0; j < k; j++){
      
double lerror = fabs((c_hwa[ii*k+j]-c_cpu[ii*k+j])/c_cpu[ii*k+j]);
      
if (lerror > error) {
        error 
= lerror;
        valueCPU 
= c_cpu[ii*k+j];
        valueGPU 
= c_hwa[ii*k+j];
        index_i 
= ii;
        index_j 
= j;
      }

    }

  }


  
if (error > 2e-06{
    fprintf( stdout, 
"\n\nThe error is %e with index %d:%d @ %e (CPU) / %e (GPU)\n", error, index_i, index_j, valueCPU, valueGPU);
    fprintf( stdout, 
"The error is is too big!\n");
    
return -1;
  }



  fprintf( stdout, 
"\n\n---- Results ----");
  fprintf( stdout, 
"\n");
  fprintf( stdout, 
"Sizes of matrices: M:%i  N:%i  K:%i\n\n", m, n, k);
  fprintf( stdout, 
"Best HWA time    : %f ms\n", best_measure_GPU / 1e3 );
  fprintf( stdout, 
"Mean HWA time    : %f ms\n", sum_measure_GPU / NB_RUNS / 1e3);
  fprintf( stdout, 
"\n");
  fprintf( stdout, 
"Best CPU time    : %f ms\n", best_measure_CPU / 1e3 );
  fprintf( stdout, 
"Mean CPU time    : %f ms\n", sum_measure_CPU / NB_RUNS / 1e3);
  fprintf( stdout, 
"\n");
  fprintf( stdout, 
"Global HWA time  : %f ms\n", global_GPU_time / 1e3 );
  fprintf( stdout, 
"Global CPU time  : %f ms\n", global_CPU_time / 1e3 );
  fprintf( stdout, 
"\n");
  fprintf( stdout, 
"Speed-up         : %f (computed on the best time)",
           ((
float)best_measure_CPU)/best_measure_GPU);


  fprintf( stdout, 
"\n");

  free(my_a);
  free(my_b);
  free(c_hwa);
  free(c_cpu);

  
return 0;
}


注意上述代碼中,測試了兩次統一個函數的執行結果,下面加入兩句簡單的指令,然后編譯執行下,看一下加速比情況。

在第31與第32行插入一下語句:

 

#pragma hmpp mylab codelet, target=CUDA, args[*].transfer=atcall

在138行插入:

 

 

#pragma hmpp mylab callsite

編譯執行:

[]$hmpp --codelet-required gcc source.c

執行結果:

---- Initialization of the Matrices ----

---- Running calculations ----
Run on GPU
0 1 2 3 4 

Run on CPU
0 1 2 3 4 

---- Results ----
Sizes of matrices: M:256  N:256  K:256

Best HWA time    : 1.436000 ms
Mean HWA time    : 21.837000 ms

Best CPU time    : 86.995000 ms
Mean CPU time    : 87.583000 ms

Global HWA time  : 109.192000 ms
Global CPU time  : 437.922000 ms

Speed-up         : 60.581478 (computed on the best time)


加速比是60倍多!我只是鍵入了兩行指令而已!!

 

當然HMPP并沒有到這里這么簡單,它提供了很多指令,指令學習并不難,也就是說我們不用直接學習CUDA或者OpenCL就可以很方便的使用GPU的計算資源了。種種好處 只有在你試用之后才能知道的奧。

后面的博客我還會講解更多的指令,還有一些有意思的細節。歡迎大家關注奧!

 

posted on 2012-10-21 11:42 jackdong 閱讀(1658) 評論(0)  編輯 收藏 引用 所屬分類: OpenACC
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            中文亚洲视频在线| 欧美丝袜第一区| 99天天综合性| 欧美激情一区二区三区不卡| 欧美在线三级| 午夜精品短视频| 欧美日韩在线视频首页| 亚洲欧洲在线一区| 影音先锋久久久| 久久av一区| 久久综合久久久| 1024成人网色www| 久久视频这里只有精品| 欧美福利视频在线观看| 亚洲激情视频网站| 欧美电影在线| 亚洲美女色禁图| 亚洲一二三区在线| 国产精品人成在线观看免费 | 亚洲级视频在线观看免费1级| 久久国产精品99精品国产| 久久久综合网| 亚洲高清视频一区| 欧美激情精品久久久| 一本久道久久久| 久久国产福利| 亚洲电影免费在线观看| 欧美人与性禽动交情品| 一区二区欧美激情| 久久久久久久久久看片| 亚洲国产另类久久久精品极度| 免费在线观看日韩欧美| 9l视频自拍蝌蚪9l视频成人| 久久精品人人做人人爽电影蜜月| 狠狠干成人综合网| 欧美成人免费在线观看| 中日韩美女免费视频网站在线观看| 欧美一区二区三区另类| 伊人男人综合视频网| 欧美极品aⅴ影院| 亚洲免费影视| 欧美大成色www永久网站婷| 中国成人黄色视屏| 国内精品亚洲| 欧美日韩国产色视频| 性欧美大战久久久久久久久| 欧美sm极限捆绑bd| 亚洲一区二区三区四区在线观看| 国产午夜亚洲精品理论片色戒| 久久综合久久美利坚合众国| 亚洲免费观看在线视频| 欧美资源在线观看| 一区二区三区欧美激情| 一区二区三区在线观看国产| 国产精品jvid在线观看蜜臀| 久久久成人网| 在线亚洲国产精品网站| 欧美mv日韩mv国产网站app| 亚洲先锋成人| 在线精品一区| 国产精品美女视频网站| 免费成人黄色片| 午夜精品www| 91久久久久久久久久久久久| 久久国产精品亚洲va麻豆| 一本色道久久综合精品竹菊 | 午夜精品久久久久久久99水蜜桃| 在线观看亚洲精品| 国产精品久久久久毛片软件 | 欧美视频免费| 久久久精品一区二区三区| 夜夜爽av福利精品导航| 欧美大片免费观看| 久久成人综合网| 亚洲无限乱码一二三四麻| 在线免费观看欧美| 国产午夜亚洲精品羞羞网站| 国产精品高潮呻吟| 欧美日本高清一区| 欧美成人免费在线观看| 久久免费少妇高潮久久精品99| 亚洲一级影院| 亚洲巨乳在线| 亚洲国产裸拍裸体视频在线观看乱了中文 | 欧美日韩不卡一区| 男人的天堂亚洲| 久久久国产视频91| 先锋影音久久久| 亚洲一区二区三区视频播放| 日韩视频一区二区| 亚洲乱码久久| 91久久精品一区| 亚洲国产va精品久久久不卡综合| 欧美xx69| 欧美激情aⅴ一区二区三区| 蜜臀久久99精品久久久画质超高清 | 一区在线观看| 国产真实久久| 国产一区二区在线观看免费播放| 国产美女精品视频| 国产精品一区二区你懂的| 国产精品成人免费视频 | 久久精品亚洲国产奇米99| 性高湖久久久久久久久| 亚洲欧美中文日韩v在线观看| 亚洲一区二区综合| 亚洲欧美激情视频| 午夜欧美大片免费观看| 欧美一区观看| 久久夜色精品国产欧美乱极品| 久久精品最新地址| 久久午夜视频| 欧美高清免费| 欧美日韩一区二区在线观看视频| 欧美三级视频在线播放| 国产精品久久久久久久久久免费 | 亚洲精品日韩在线| 9久re热视频在线精品| 亚洲在线观看免费视频| 欧美一级免费视频| 久久先锋资源| 欧美日本韩国一区二区三区| 国产精品a久久久久久| 国产麻豆午夜三级精品| 国产自产在线视频一区| 亚洲欧洲另类国产综合| 亚洲深夜福利| 欧美中文字幕| 亚洲第一黄色网| 中文日韩在线视频| 欧美专区18| 女人色偷偷aa久久天堂| 欧美色精品天天在线观看视频| 欧美激情久久久| 欧美一区二区三区四区在线观看| 久久激情综合| 欧美成年人视频网站| 欧美日韩一区二区在线观看视频| 国产欧美综合在线| 91久久久在线| 性欧美8khd高清极品| 欧美高清在线精品一区| 亚洲性xxxx| 久久综合九色| 国产精品久久久久国产a级| 伊人久久久大香线蕉综合直播| 一区二区三区欧美日韩| 久久午夜色播影院免费高清| 亚洲精品乱码久久久久久按摩观 | 亚洲精品国精品久久99热一| 亚洲欧美国产毛片在线| 老司机精品导航| 国产精品福利av| 亚洲国产综合91精品麻豆| 亚洲免费在线视频| 欧美成人精品一区| 亚洲男女自偷自拍图片另类| 美女精品在线观看| 国产精品视频免费观看www| 日韩视频在线观看国产| 久久这里有精品15一区二区三区 | 欧美激情精品久久久久久久变态| 国产精品99久久久久久有的能看| 久久亚洲春色中文字幕| 国产精品久久久久久久7电影| 亚洲精华国产欧美| 久久伊人精品天天| 亚洲字幕在线观看| 欧美日韩精品在线观看| 亚洲国产成人精品视频| 久久露脸国产精品| 亚洲综合成人婷婷小说| 欧美日韩国产成人在线91| 黄色资源网久久资源365| 性欧美暴力猛交69hd| 亚洲麻豆视频| 欧美承认网站| 亚洲国产美女精品久久久久∴| 久久久噜久噜久久综合| 亚洲欧美电影院| 国产精品成人免费精品自在线观看| 亚洲看片免费| 欧美国产第一页| 久久伊人免费视频| 狠狠爱成人网| 久久视频一区二区| 欧美影院一区| 一本一本a久久| 欧美激情一区二区三区在线视频观看| 韩国精品久久久999| 久久福利影视| 欧美一区二区三区在线免费观看| 国产欧美日韩综合一区在线观看| 亚洲综合成人婷婷小说| av成人激情| 欧美午夜免费| 亚洲视频欧美视频| 一区二区三区四区国产精品| 欧美三级乱人伦电影| 亚洲一区二区三区四区五区午夜 |