Domanda

Sto cercando di calcolare il numero di transizioni che sarebbero realizzati in un percorso di GOL Conway per una matrice pxq per n iterazioni. Ad esempio, in 1 iterazione con lo stato iniziale essendo 1 lampeggiante (come sotto). ci sarebbero 5 transizioni (2 nascite, 1 sopravvivenza, 2 morti da sottopopolamento). Ho già ottenuto questo lavoro, ma vorrei convertire questa logica da eseguire utilizzando CUDA. Qui di seguito è quello che voglio a porta per CUDA.

alt text     codice:

    static void gol() // call this iterations x's
    {
        int[] tempGrid = new int[rows * cols]; // grid holds init conditions
        for (int i = 0; i < rows; i++)
        {
            for (int j = 0; j < cols; j++)
            {
                tempGrid[i * cols + j] = grid[i * cols + j];
            }
        }

        for (int i = 0; i < rows; i++)
        {
            for (int j = 0; j < cols; j++)
            {
                int numNeighbors = neighbors(i, j); // finds # of neighbors

                if (grid[i * cols + j] == 1 && numNeighbors > 3)
                {
                    tempGrid[i * cols + j] = 0;
                    overcrowding++;
                }
                else if (grid[i * cols + j] == 1 && numNeighbors < 2)
                {
                    tempGrid[i * cols + j] = 0;
                    underpopulation++;
                }
                else if (grid[i * cols + j] == 1 && numNeighbors > 1)
                {
                    tempGrid[i * cols + j] = 1;
                    survival++;
                }
                else if (grid[i * cols + j] == 0 && numNeighbors == 3)
                {
                    tempGrid[i * cols + j] = 1;
                    birth++;
                }
            }
        }

        grid = tempGrid;
    }
È stato utile?

Soluzione

Il rallentamento principale sarà l'accesso alla memoria principale. Quindi io suggerirei che si sceglie una dimensione di blocco filo abbastanza grande basata su hardware che avete a disposizione. 256 (16x16) è una buona scelta per la compatibilità cross-hardware. Ognuno di questi blocchi di filettatura sta per calcolare i risultati per una sezione leggermente più piccolo del consiglio - se è stato utilizzato 16x16, faranno calcolano i risultati per una sezione 14x14 del consiglio di amministrazione, in quanto non v'è un bordo un elemento. (La ragione per usare un blocco 16x16 a 14x14 calcolare un pezzo piuttosto che un pezzo 16x16 è per la memoria leggere coalescenza.)

Dividere il bordo fino in (diciamo) 14x14 pezzi; questa è la vostra griglia (organizzato tuttavia si vede in forma, ma molto probabilmente qualcosa di simile board_width / 14, board_height / 14.

Nei kernel, hanno ogni carico filo suo elemento nella memoria condivisa. syncthreads allora. Poi hanno gli intermedi 14x14 elementi calcolare il nuovo valore (utilizzando i valori memorizzati nella memoria condivisa) e scrivere di nuovo nella memoria globale. L'uso di memoria condivisa aiuta a minimizzare letture e le scritture globale. Questo è anche il motivo per avere la dimensione del blocco di filettatura più grande possibile -. I bordi e gli angoli sono "sprecati" accessi di memoria globale, dal momento che i valori recuperati ci si abitua solo 1 o 3 volte, non 9 volte

Altri suggerimenti

Ecco un modo si potrebbe procedere:

  1. Ogni thread rende il calcolo per 1 elemento della rete
  2. Ogni thread primi carichi fino un elemento dalla griglia principale nella memoria condivisa
  3. Filati sul bordo della necessità blocco di filettatura anche per caricare elementi di contorno
  4. Ogni thread può quindi fare la loro sopravvivenza calcolo in base al contenuto della memoria condivisa
  5. Ogni thread quindi scrive il risultato di nuovo alla memoria principale
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top