1

n回の反復のpxq行列に対してConwayのGOLの実行で行われる遷移の数を計算しようとしています。たとえば、初期状態が1回の点滅である1回の反復が与えられます(以下のように)。5つの遷移があります(2つの出生、1つの生存、2つの過疎による死亡)。私はすでにこれを機能させていますが、このロジックをCUDAを使用して実行するように変換したいと思います。以下は私がCUDAに移植したいものです。

代替テキスト コード:

    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;
    }
4

2 に答える 2

4

主な速度低下は、メインメモリへのアクセスになります。したがって、使用可能なハードウェアに基づいて、大きなスレッドブロックサイズを選択することをお勧めします。256(16x16)は、ハードウェア間の互換性に適しています。これらのスレッドブロックはそれぞれ、ボードのわずかに小さいセクションの結果を計算します。16x16を使用した場合、要素の境界が1つあるため、ボードの14x14セクションの結果が計算されます。(16x16チャンクではなく16x16ブロックを使用して14x14チャンクを計算する理由は、メモリ読み取りの合体のためです。)

ボードを(たとえば)14x14のチャンクに分割します。それがあなたのグリッドです(適切と思われる方法で編成されていますが、おそらく、のようなものboard_width / 14ですboard_height / 14

カーネル内で、各スレッドにその要素を共有メモリにロードさせます。次に、syncthreads。次に、中央の14x14要素に(共有メモリに格納されている値を使用して)新しい値を計算させ、それをグローバルメモリに書き戻します。共有メモリを使用すると、グローバルな読み取りと書き込みを最小限に抑えることができます。これは、スレッドブロックサイズをできるだけ大きくする理由でもあります。ここでフェッチされた値は9回ではなく、1回または3回しか使用されないため、エッジとコーナーは「無駄な」グローバルメモリアクセスです。

于 2010-12-14T15:39:59.680 に答える
0

続行する方法の1つは次のとおりです。

  1. 各スレッドは、グリッドの1つの要素の計算を行います
  2. 各スレッドは、最初にメイングリッドから共有メモリに1つの要素をロードします
  3. スレッドブロックのエッジにあるスレッドも、境界要素をロードする必要があります
  4. 各スレッドは、共有メモリの内容に基づいてサバイバル計算を行うことができます
  5. 次に、各スレッドは結果をメインメモリに書き戻します
于 2010-12-14T13:33:13.153 に答える