0

私は答えを見つけることができませんが、それは単純なものでなければなりません。私はセルオートマトンの状態を計算する必要があるプログラムを書いています.CUDAがどのように機能するかを理解するために、最初に非常に単純なプログラムを作成しようとしました. 行列を取り、すべてのスレッドはそのセルと、このセルの上下にあるセルの値をインクリメントする必要があります。したがって、次のマトリックスを指定すると:

[0 0 0 0 0 0 0]
[0 0 0 0 0 0 0]
[0 0 0 0 0 0 0]
[0 0 0 0 0 0 0]
[0 0 0 0 0 0 0]
[0 0 0 0 0 0 0]
[0 0 0 0 0 0 0]

次の結果が得られることを期待しています。

[2 2 2 2 2 2 2]
[3 3 3 3 3 3 3]
[3 3 3 3 3 3 3]
[3 3 3 3 3 3 3]
[3 3 3 3 3 3 3]
[3 3 3 3 3 3 3]
[2 2 2 2 2 2 2]  

最初の行の値は 2 です。これは、最初の行の値をもう一度インクリメントできる行がないためです。同様の方法で、最後の行の値は 2です。
しかし、次のような行列を取得しています。

[2 2 2 2 2 2 2]
[3 3 3 3 3 3 3]
[3 3 3 3 3 3 3]
[3 3 3 3 2 2 2]
[2 2 2 2 2 2 2]
[2 2 2 2 3 3 3]
[2 2 2 2 2 2 2]  

そして、4行目、5行目、6行目に2の値がある理由を理解できません.2ではなく3でなければなりません.
ここに私のコードがあります:

import numpy
import pycuda.autoinit
import pycuda.driver as cuda

from pycuda.compiler import SourceModule

w = 7

mod = SourceModule("""
        __global__ void diffusion(  int* result, int width, int height) {

            int xIndex = blockDim.x * blockIdx.x + threadIdx.x;
            int yIndex = blockDim.y * blockIdx.y + threadIdx.y;

            int flatIndex = xIndex + width * yIndex;
            int topIndex = xIndex + width * (yIndex - 1);
            int bottomIndex = xIndex + width * (yIndex + 1);

            int inc = 1;

            result[flatIndex] += inc;

            result[bottomIndex] += inc;

            result[topIndex] += inc;
        }

        """)

diff_func   = mod.get_function("diffusion")


def diffusion(res):

    height, width = numpy.int32(len(res)), numpy.int32(len(res[0]))

    diff_func(
        cuda.InOut(res),
        width,
        height,
        block=(w,w,1)
        )

def run(res, step):

    diffusion(res)
    print res

res   = numpy.array([[0 \
                        for _ in xrange(0, w)]\
                        for _ in xrange(0, w)], dtype='int32')

run(res, 0)  

もう 1 つ興味深い点: 次の行のいずれかをコメントすると、次のようになります。

result[bottomIndex] += inc;
result[topIndex] += inc;  

すべてが期待どおりに機能し、予期しない値はありません。場合によっては、CUDA が 1 つのスレッドで隣接する 3 つのセルの値を処理できないようです。

4

1 に答える 1

2

メモリ競合と呼ばれるものがあります。複数の独立したスレッドがメモリ内の同じ値を同時に更新しようとしています。CUDA メモリ モデルは、2 つのスレッドが同じメモリ位置を同時に更新しようとしたときに何が起こるかを定義していません。

解決策は、アトミック メモリ操作 (詳細については CUDA プログラミング ガイドを参照) を使用するか、隣接するセルを更新するための別のアプローチ (たとえば、グリッドに色を付けて、グリッドを通過する別のパスで色付きのセルのように更新する) のいずれかです。

于 2013-02-10T09:20:41.503 に答える