CUDA-Thread-Ausführungsreihenfolge

  • Ich habe den folgenden Code für ein CUDA-Programm:

     #include <stdio.h>
    
    #define NUM_BLOCKS 4
    #define THREADS_PER_BLOCK 4
    
    __global__ void hello()
    {  
    
       printf("Hello. I'm a thread %d in block %d\n", threadIdx.x, blockIdx.x);
    
    }
    
    
    int main(int argc,char **argv)
    {
        // launch the kernel
        hello<<<NUM_BLOCKS, THREADS_PER_BLOCK>>>();
    
        // force the printf()s to flush
        cudaDeviceSynchronize();
    
        return 0;
    }
     

    in welchem Jeder Thread wird seine threadIdx.x und blockIdx.x drucken. Eine mögliche Ausgabe dieses Programms ist folgende:

     Hello. I'm a thread 0 in block 0
    Hello. I'm a thread 1 in block 0
    Hello. I'm a thread 2 in block 0
    Hello. I'm a thread 3 in block 0
    Hello. I'm a thread 0 in block 2
    Hello. I'm a thread 1 in block 2
    Hello. I'm a thread 2 in block 2
    Hello. I'm a thread 3 in block 2
    Hello. I'm a thread 0 in block 3
    Hello. I'm a thread 1 in block 3
    Hello. I'm a thread 2 in block 3
    Hello. I'm a thread 3 in block 3
    Hello. I'm a thread 0 in block 1
    Hello. I'm a thread 1 in block 1
    Hello. I'm a thread 2 in block 1
    Hello. I'm a thread 3 in block 1
     

    Wenn Sie das Programm mehrmals ausführen, bekomme ich ähnliche Ergebnisse Blockreihenfolge ist zufällig. In der obigen Ausgabe haben wir beispielsweise diese Blockreihenfolge 0, 2, 3, 1. Wenn Sie das Problem erneut ausführen, erhalten Sie 1,2,3, 0. Dies wird erwartet. Die Thread-Reihenfolge in jedem Block ist jedoch immer 0,1,2,3. Warum passiert dies? Ich dachte, es wäre auch zufällig.

    Ich habe versucht, meinen Code zu ändern, um den Thread 0 in jedem Block zu zwingen, um länger auszuführen. Ich habe es so gemacht:

     __global__ void hello()
    {  
    
        if (threadIdx.x == 0)
        {
            int k = 0;
            for ( int i = 0; i < 1000000; i++ )
            {
                k = k + 1;
            }
        }
    
       printf("Hello. I'm a thread %d in block %d\n", threadIdx.x, blockIdx.x);
    
    }
     

    Ich würde eine Thread-Reihenfolge von 1,2,3, 0 erwarten. Ich erhielt jedoch ein ähnliches Ergebnis wie das oben gezeigte, bei dem die Thread-Reihenfolge immer 0, 1, 2, 3 war. Warum passiert das?

    28 February 2016
    talonmiescatalyst294
2 answers
  • Die Thread-Reihenfolge in jedem Block ist jedoch immer 0,1,2,3. Warum passiert dies? Ich dachte, es wäre auch zufällig.

    Mit 4 Threads pro Block starten Sie nur einen Warp pro Block. Eine Warp ist die Ausführungseinheit (und Zeitplanung und Ressourcenzuweisung) in CUDA, kein Thread. Derzeit besteht ein Warp aus 32 Threads.

    Dies bedeutet, dass alle 4 Ihrer Threads (da in diesem Fall kein bedingtes Verhalten vorliegt) in lockstep ausgeführt werden . Wenn sie den Funktionsaufruf printf erreichen, führen sie alle den Aufruf dieser Funktion in derselben Codezeile aus, in Lockstep .

    In dieser Situation stellt sich also die Frage, wie die CUDA-Laufzeit diese "gleichzeitigen" Funktionsaufrufe verteilt. Die Antwort auf diese Frage ist nicht spezifiziert, aber nicht "zufällig". Daher ist es vernünftig, dass sich die Reihenfolge des Versandes für Operationen innerhalb eines Warp nicht von Run zu Run ändert.

    Wenn Sie genug Threads starten, um mehrere Warps pro Block zu erstellen, und möglicherweise auch einschließen Wenn Sie das Verhalten zwischen Warps verteilen oder "randomisieren" wollen, sollten Sie in der Lage sein, printf -Operationen zu sehen, die von separaten Warps stammen, die in "zufälliger" Reihenfolge auftreten.

    25 May 2015
    Robert CrovellaSayan
  • Um den zweiten Teil Ihrer Frage zu beantworten, warten die Threads, bei denen threadIdx.x != 0 am Konvergenzpunkt nach der Anweisung if wartet, auf []. Sie gehen nicht zur Anweisung printf über, bis Thread 0 den Block if abgeschlossen hat.

    25 May 2015
    Jeff Ames