2012-07-15 2 views
0

J'ai le code suivant qui parcourt progressivement une chaîne de bits et les réorganise en blocs de 20 octets. J'utilise 32 * 8 blocs avec 40 fils par bloc. Cependant, le processus prend quelque chose comme 36ms sur mon GT630M. Y a-t-il une optimisation supplémentaire que je peux faire? Surtout en ce qui concerne la suppression de l'if-else dans la boucle la plus interne.Optimisation d'un noyau de manipulation Bit-Wise

__global__ void test(unsigned char *data) 
{ 
    __shared__ unsigned char dataBlock[20]; 
    __shared__ int count; 
    count = 0; 

    unsigned char temp = 0x00; 

    for(count=0; count<(streamSize/8); count++) 
    { 
     for(int i=0; i<8; i++) 
     { 
      if(blockIdx.y >= i) 
       temp |= (*(data + threadIdx.x*(blockIdx.x + gridDim.x*(i+count)))&(0x01<<blockIdx.y))>>(blockIdx.y - i); 
      else 
       temp |= (*(data + threadIdx.x*(blockIdx.x + gridDim.x*(i+count)))&(0x01<<blockIdx.y))<<(i - blockIdx.y); 
     } 
     dataBlock[threadIdx.x] = temp; 
      //do something 

    } 

} 
+0

Vous pouvez commencer par * toujours * en utilisant des tailles de blocs qui sont des multiples arrondis de la taille de la chaîne. L'utilisation de 40 threads par bloc gaspille environ 37% de tous les cycles disponibles sur votre GPU. – talonmies

+0

Vous pouvez également lancer plusieurs threads en même temps pour masquer les temps de latence. –

+0

Votre boucle externe écrit 'dataBlock [threadIdx.x] = temp;' chaque itération - de sorte que vous écrasez le même emplacement 'streamSize/8' fois. Déplacez cette ligne en dehors de la boucle. – harrism

Répondre

1

Il est pas clair ce que votre code tente d'accomplir, mais un couple des opportunités évidentes sont:

1) si possible, utilisez des mots de 32 bits au lieu de char non signé.

2) utiliser des tailles de blocs qui sont des multiples de 32.

3) Le code conditionnel ne peut vous coûter autant que vous attendez. Vous pouvez vérifier en compilant avec --cubin --gpu-architecture sm_xx (où xx est la version SM de votre matériel cible), et en utilisant cuobjdump --dump-sass sur le fichier cubin résultant pour regarder l'assemblage généré. Vous devrez peut-être modifier le code source pour loft la sous-expression commune dans une variable distincte, et/ou utiliser l'opérateur ternaire? : pour suggérer au compilateur d'utiliser la prédication.

+1

Et idéalement, utilisez au moins 64 threads par bloc. Les blocs à 32 fils sur les appareils sm_30 et les appareils plus anciens limiteront l'occupation (et donc la capacité à couvrir la latence de la mémoire) puisque chaque SM peut avoir au plus 8 blocs résidents. Avec 32 threads par bloc, vous aurez donc au maximum 8 warps par SM, alors que vous en aurez 16 si vous utilisez des blocks à 64 threads. – harrism