• Nenhum resultado encontrado

com o OpenTuner

Com a escolha dos algoritmos, o próximo passo foi desenvolver scripts em Python para a ferramenta OpenTuner que tem como função a execução dos benchmarks com cada uma das configurações e então escolher a melhor configuração com base no resultado de métricas coletadas do hardware pela ferramenta de perfilamento nvprof. Vale ressaltar que foi criado um script para cada métrica e para cada algoritmo. Nesta seção será apresentado somente o

script desenvolvido para o algoritmo GEMM, os demais scripts podem ser consultados no

repositório do GitHub5.

Como demonstrado na Seção 2.4.1, o OpenTuner trabalha em três passos, definição do espaço de busca, método manipulator que realiza as escolhas e o método run que realiza a execução e a escolha do mélhor resultado a partir da métrica escolhida.

Na primeira versão desenvolvida para o OpenTuner no algoritmo GEMM foi especificado o espaço de busca aberto na qual ele buscava todos os valores dentro de um espaço mínimo e máximo, esse mínimo e máximo é denotado por um bloco de parâmetros que pode ser visto no Código 4.5.

  1 . . . 2BLOCO_PARAMETROS = [ 3 (’ kernel ’, 0 , 0 ) , 4 (’gx ’, 1 , 2 1 4 7 4 8 3 6 4 7 ) , 5 (’gy ’, 1 , 6 5 5 3 5 ) , 6 (’gz ’, 1 , 6 5 5 3 5 ) , 7 (’bx ’, 1 , 1 0 2 4 ) , 8 (’by ’, 1 , 1 0 2 4 ) , 9 (’bz ’, 1 , 6 4 ) , 10 (’ni ’, 6 4 , 6 4 ) , 11 (’nj ’, 6 4 , 6 4 ) , 12 (’nk ’, 6 4 , 6 4 ) , 13 (’ gpuId ’, 0 , 0 ) 14 ] 15 . . .  

Código 4.5. Espaço de busca aberto implementado no OpenTuner

Com esse bloco de parâmetros criado o método run escolhia um valor dentro do mínimo e máximo e realizava a execução do algoritmo GEMM para as configurações escolhidas. Contudo, na maneira de busca aberta ocasionava que a maioria das escolhas era escolhas inválidas (escolhas que não seguem as regras especificadas na Seção 3.1), ocasionando em testes errados, bem como o tempo gasto para a execução era alto, fazendo com que mudássemos a forma de buscar as configurações.

Assim, foi desenvolvido uma segunda versão que buscaria somente no espaço de busca de configurações válidas. Desta forma foi criado primeiramente um script na linguagem C que escreve em um arquivo todas as configurações válidas para um tamanho 𝑁, logo após o OpenTuner cria uma lista destas configurações e encaminha para o método run que realiza os testes. O Código 4.6 apresenta parte do script desenvolvido em C para escrever em um arquivo as configurações válidas e o Código 4.7 mostra uma parte do arquivo criado pelo script em C. Pode ser visualizado todo o script e os arquivos gerados no repositório do GitHub6.

 

1 . . .

2 f o r ( bz = 1 ; bz <= min ( i t e r a t i o n s ,MAX_BLOCK_Z) ; bz++) {

3 f o r ( by = 1 ; by <= min ( ( i t e r a t i o n s / bz ) ,MAX_BLOCK_Y) ; by++) {

4 f o r ( bx = 1 ; bx <= min ( ( ( i t e r a t i o n s / bz ) / by ) ,MAX_BLOCK_X) ; bx++) { 5 f o r ( gx = 1 ; gx <= min ( ( ( ( i t e r a t i o n s / bz ) / by ) / bx ) ,MAX_GRID_X) ; gx++) { 6 f o r ( gy = 1 ; gy <= min ( ( ( ( ( i t e r a t i o n s / bz ) / by ) / bx ) / gx ) , MAX_GRID_Y) ; gy++) { 7 f o r ( gz = 1 ; gz <= min ( ( ( ( ( ( i t e r a t i o n s / bz ) / by ) / bx ) / gx ) / gy ) ,MAX_GRID_Z) ; gz++) { 6<https://github.com/jfilhoGN/tcc_cuda_opentuner_joao/tree/master/benchmarks/gen-configs>

8 c o n f B l o c k = bx ∗ by ∗ bz ; 9 c o n f G r i d = gx ∗ gy ∗ gz ; 10 c o n f i g = c o n f B l o c k ∗ c o n f G r i d ; 11 // E v i c t k e r n e l d i v e r g e n c e , b l o c k s w i t h m u l t i p l y warp s i z e . 12 i f ( ( c o n f B l o c k <= 1 0 2 4 ) && ( c o n f i g == i t e r a t i o n s ) && ( c o n f B l o c k % 32 == 0 ) ) { 13 p r i n t f(" ’ gx:%d , gy:%d , gz :%d , bx:%d , by:%d , bz :%d , ’ \n ", gx , gy , gz , bx , by , bz ) ; 14 c o u n t C o n f i g ++; 15 } 16 } 17 } 18 } 19 } 20 } 21 } 22 . . .  

Código 4.6. Espaço de busca aberto implementado no OpenTuner

  1 . . . 2 ’gx :1 , gy :16 , gz :8 , bx :32 , by :1 , bz :1 , ’ 3 ’gx :1 , gy :32 , gz :4 , bx :32 , by :1 , bz :1 , ’ 4 ’gx :1 , gy :64 , gz :2 , bx :32 , by :1 , bz :1 , ’ 5 ’gx :1 , gy :128 , gz :1 , bx :32 , by :1 , bz :1 , ’ 6 ’gx :2 , gy :1 , gz :64 , bx :32 , by :1 , bz :1 , ’ 7 . . .  

Código 4.7. Parte do arquivo criado com as configurações válidas para N

Com a criação do espaço de busca é enviado uma lista para o método run com os valores dos grids e blocos onde ele estará realizando os testes e os "cortes"que julgar necessário através dos algoritmos de busca. Exemplo do método run é apresentado no Código 4.8. Com este método funcionando o OpenTuner cria um comando em linha de comando no formato do Código 5.2.   1 . . . 2 while True : 3 c o n f i g u r a t i o n = d e s i r e d _ r e s u l t . c o n f i g u r a t i o n . d a t a 4 print " Configuration : ", c o n f i g u r a t i o n

5 c f g = { match . group ( 1 ) : match . group ( 2 ) f o r match in r e . f i n d i t e r (r" ([^:]+) :(\ S +) \s * ,[ \n]", c o n f i g u r a t i o n [’ config ’] ) }

6 print " CFG : ", c f g

7 c o n f B l o c k = i n t ( c f g [’bx ’] ) ∗ i n t ( c f g [’by ’] ) ∗ i n t ( c f g [’bz ’] ) 8 c o n f G r i d = i n t ( c f g [" ’gx "] ) ∗ i n t ( c f g [’gy ’] ) ∗ i n t ( c f g [’gz ’] )

9 c o n f i g = c o n f B l o c k ∗ c o n f G r i d 10 print " ConfBlock "+ s t r ( c o n f B l o c k ) 11 print " ConfGrid " + s t r ( c o n f G r i d ) 12 i f ( ( c o n f B l o c k <= 1 0 2 4 ) and ( c o n f B l o c k % 32 == 0 ) and ( c o n f i g == n ) ) : 13 break 14 e l s e : 15 return R e s u l t ( t i m e=FAIL_PENALTY)

16 print " compiled : ", ’ true ’ i f c o m p i l e d e l s e ’ false ’ 17 i f not c o m p i l e d :

18 print " Compiling the program ... "

19 gcc_cmd = ’ nvcc -I / usr / local / cuda / include -L / usr / local / cuda / lib64 - ccbin =g ++ -6 gemm . cu - lcuda -lm -o gemm - cuda . exe ’

20 c o m p i l e _ r e s u l t = s e l f . c a l l _ p r o g r a m ( gcc_cmd ) 21 a s s e r t c o m p i l e _ r e s u l t [’ returncode ’] == 0 22 print " OK .\ n"

23 global c o m p i l e d

24 c o m p i l e d = not c o m p i l e d

25 run_cmd = ’ nvprof -- metrics achieved_occupancy ./ gemm - cuda . exe ’ 26 . . .

 

Código 4.8. Exemplo do método run para o algoritmo GEMM

Com a execução do comando gerado a partir do método run é enviado para o método

get_metric_from_app_output que verifica o valor que foi gerado e retorna um valor da

métrica que é usado para realizar a comparação e os "cortes"com os algoritmos de busca. Em nossa implementação neste método fica especificado a criação de um arquivo .csv que contém todas as configurações e resultados gerados, no Código 4.9 é demonstrado a implementação do método get_metric_from_app_output. Quando encontrado a melhor configuração é gerado um arquivo .json contendo a melhor configuração.

 

1 . . .

2 def get_metric_from_app_output ( s e l f , app_output , c o n f i g u r a t i o n , k e r n e l ,

gpuId ) : 3 m e t r i c _ v a l u e = 0 . 0 4 l i n e s = app_output . s p l i t ("\n") 5 f o r c u r r e n t _ l i n e in l i n e s : 6 s t r g = "" + c u r r e n t _ l i n e 7 i f s t r g . f i n d (" Occupancy ") > −1: 8 i d x = s t r g . i n d e x (" Occupancy ") 9 s u b s r t g = s t r g [ i d x : ] . s p l i t (" ") 10 print " substrg : ", s u b s r t g 11 m e t r i c _ v a l u e = f l o a t ( s u b s r t g [ 3 ] ) 12 print " achieved_occupancy : ", m e t r i c _ v a l u e 13 c o n f i g u r a t i o n = s t r ( c o n f i g u r a t i o n )

14 c o n f i g u r a t i o n = c o n f i g u r a t i o n . r e p l a c e ("{", s t r ( k e r n e l )+" ,") . r e p l a c e (":"," ") . r e p l a c e ("}","") 15 c o n f i g u r a t i o n = c o n f i g u r a t i o n . r e p l a c e (" ’gx ","") . r e p l a c e (" ’gy ’","") . r e p l a c e (" ’gz ’","") . r e p l a c e (" ’bx ’","") . r e p l a c e (" ’by ’","") . r e p l a c e (" ’bz ’","") . r e p l a c e (" ’","") . r e p l a c e (" \" ","") 16 r e s u l t a d o = m e t r i c _ v a l u e

17 a r q u i v o _ c s v = open (" diretorio_saida "+s t r ( s y s . a r g v [ 2 ] ) +". csv ","a")

18 a r q u i v o _ c s v . w r i t e (" Kernel ,gx ,gy ,gz ,bx ,by ,bz , gpuId , occupancy \n")

19 a r q u i v o _ c s v . w r i t e ( s t r ( c o n f i g u r a t i o n )+" ,"+s t r ( gpuId )+" ,"+s t r ( r e s u l t a d o )+"

\n")

20 return m e t r i c _ v a l u e 21 . . .

 

Código 4.9. Exemplo do método get_metric_from_app_output para o algoritmo GEMM

Com o funcionamento exato do código é criado um arquivo .csv contendo as configurações e também um arquivo .json com a melhor configuração encontrada. No Código 4.10 é visto exemplo dos dois arquivos para 𝑁 = 64 para a métrica achieved_occupancy.

  1 . . . Arquivo . c s v 2 Ke rn el , gx , gy , gz , bx , by , bz , gpuId , occupancy 3 0 , 4 , 2 , 2 , 3 2 , 2 , 4 , 0 , 0 . 9 3 0 3 4 0 , 8 , 2 , 4 , 8 , 4 , 2 , 0 , 0 . 9 3 0 6 3 4 5 0 , 2 , 1 , 1 6 , 1 , 1 2 8 , 1 , 0 , 0 . 9 3 2 1 5 4 6 . . . 7 . . . Arquivo . j s o n

8 {" ni ": 6 4 , " nj ": 6 4 , " nk ": 6 4 , " kernel ": 0 , " gpuId ": 0 , " config ": " ’gx :64 , gy :1 , gz :2 , bx :1 , by :2 , bz :16 , ’ \n"}

9 . . .

 

Código 4.10. Parte do arquivo criado com as configurações válidas para N

Para uma melhor organização foi criado um código OpenTuner para cada métrica que foi utilizada para gerar resultados, no presente texto é apresentado somente parte do código para a métrica achieved_occupancy, para visualizar os outros códigos bem como este código completo, pode ser visualizado no repositório do GitHub7.

Vale ressaltar que na próxima Seção 4.3 é apresentado as GPUS que foram utilizadas para os testes e também as métricas utilizadas para a escolha da melhor configuração no OpenTuner.

4.3.

Realização dos Testes e Extração da Melhor Con-

Documentos relacionados