Question

Je suis en train de calculer le nombre de transitions qui seraient faites dans une série de gol de Conway pour une matrice pxq pour n itérations. Par exemple, étant donné une itération à l'état initial étant égal à 1 clignotant (comme ci-dessous). il y aurait 5 transitions (2 naissances, une survie, 2 décès à partir de sous-population). Je l'ai déjà eu ce travail, mais je voudrais convertir cette logique pour exécuter en utilisant CUDA. Voici ce que je veux port CUDA.

text alt     Code:

    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;
    }
Était-ce utile?

La solution

Votre principal ralentissement va être principal accès à la mémoire. Je propose donc que vous choisissez une taille de bloc de fil de largish en fonction du matériel dont vous disposez. 256 (16x16) est un bon choix pour la compatibilité entre le matériel. Chacun de ces blocs de fil va calculer les résultats pour une section légèrement plus petite du conseil - si vous avez utilisé 16x16, ils calculent les résultats pour une section 14x14 du conseil d'administration, car il y a une bordure de l'élément. (La raison d'utiliser un bloc 16x16 pour calculer un bloc 14x14 plutôt que d'un morceau 16x16 est à la mémoire morte de coalescence.)

Diviser la planche vers le haut dans (par exemple) 14x14 morceaux; qui est votre grille (organisé comme bon vous semble, mais très probablement quelque chose comme board_width / 14, board_height / 14.

Dans les grains, ont chacun la charge de fil de son élément dans la mémoire partagée. Ensuite syncthreads. Puis ont les éléments 14x14 moyen calculer la nouvelle valeur (en utilisant les valeurs stockées dans la mémoire partagée) et l'écrire de nouveau dans la mémoire globale. L'utilisation de la mémoire partagée permet de minimiser les lectures global et écrit. Ceci est aussi la raison d'avoir votre taille de bloc de fil aussi grand que possible -. Les bords et les coins sont « gaspillées » accès de mémoire globale, puisque les valeurs récupérées il ne se consommaient 1 ou 3 fois, pas 9 fois

Autres conseils

Voici une façon vous pouvez procéder:

  1. Chaque fil permet le calcul de 1 'élément de la grille
  2. Chaque thread premières charges jusqu'à un élément du réseau principal dans la mémoire partagée
  3. Discussions sur le bord de la nécessité de bloc de filetage également pour charger des éléments de frontière
  4. Chaque thread peut alors faire leur calcul de survie en fonction du contenu de la mémoire partagée
  5. Chaque thread écrit ensuite leur résultat à la mémoire principale
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top