3

大きな画像を変更するという明確な目的で画像処理プログラムを作成しています。使用しているのは8165ピクセル×4915ピクセルです。GPU処理を実装するように言われたので、いろいろ調べた結果、OpenCLを使うことにしました。OpenCL C# ラッパー OpenCLTemplate の実装を開始しました。

私のコードはビットマップを取り込み、lockbits を使用してそのメモリ位置をロックします。次に、各ビットの順序を配列にコピーし、openCL カーネルを介して配列を実行すると、配列内の各ビットが反転します。次に、反転したビットをイメージのメモリ ロケーションに戻します。このプロセスを 10 個のチャンクに分割して、プログレス バーをインクリメントできるようにします。

私のコードは小さいイメージでは完全に動作しますが、大きなイメージで実行しようとすると、カーネルを実行しようとすると MemObjectAllocationFailure が発生し続けます。なぜこれを行うのかわかりません。なぜ、またはどのように修正するのかを理解するための助けをいただければ幸いです。

    using OpenCLTemplate;

    public static void Invert(Bitmap image, ToolStripProgressBar progressBar)
    {
        string openCLInvert = @"
        __kernel void Filter(__global uchar *  Img0,
                             __global float *  ImgF)

        {
            // Gets information about work-item
            int x = get_global_id(0);
            int y = get_global_id(1);

            // Gets information about work size
            int width = get_global_size(0);
            int height = get_global_size(1);

            int ind = 4 * (x + width * y );

            // Inverts image colors
            ImgF[ind]= 255.0f - (float)Img0[ind];
            ImgF[1 + ind]= 255.0f - (float)Img0[1 + ind];
            ImgF[2 + ind]= 255.0f - (float)Img0[2 + ind];

            // Leave alpha component equal
            ImgF[ind + 3] = (float)Img0[ind + 3];
        }";

        //Lock the image in memory and get image lock data
        var imageData = image.LockBits(new Rectangle(0, 0, image.Width, image.Height), ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);

        CLCalc.InitCL();

        for (int i = 0; i < 10; i++)
        {
            unsafe
            {
                int adjustedHeight = (((i + 1) * imageData.Height) / 10) - ((i * imageData.Height) / 10);
                int count = 0;

                byte[] Data = new byte[(4 * imageData.Stride * adjustedHeight)];
                var startPointer = (byte*)imageData.Scan0;

                for (int y = ((i * imageData.Height) / 10); y < (((i + 1) * imageData.Height) / 10); y++)
                {
                    for (int x = 0; x < imageData.Width; x++)
                    {
                        byte* Byte = (byte*)(startPointer + (y * imageData.Stride) + (x * 4));

                        Data[count] = *Byte;
                        Data[count + 1] = *(Byte + 1);
                        Data[count + 2] = *(Byte + 2);
                        Data[count + 3] = *(Byte + 3);
                        count += 4;
                    }
                }

                CLCalc.Program.Compile(openCLInvert);
                CLCalc.Program.Kernel kernel = new CLCalc.Program.Kernel("Filter");
                CLCalc.Program.Variable CLData = new CLCalc.Program.Variable(Data);

                float[] imgProcessed = new float[Data.Length];

                CLCalc.Program.Variable CLFiltered = new CLCalc.Program.Variable(imgProcessed);
                CLCalc.Program.Variable[] args = new CLCalc.Program.Variable[] { CLData, CLFiltered };

                kernel.Execute(args, new int[] { imageData.Width, adjustedHeight });
                CLCalc.Program.Sync();

                CLFiltered.ReadFromDeviceTo(imgProcessed);

                count = 0;

                for (int y = ((i * imageData.Height) / 10); y < (((i + 1) * imageData.Height) / 10); y++)
                {
                    for (int x = 0; x < imageData.Width; x++)
                    {
                        byte* Byte = (byte*)(startPointer + (y * imageData.Stride) + (x * 4));

                        *Byte = (byte)imgProcessed[count];
                        *(Byte + 1) = (byte)imgProcessed[count + 1];
                        *(Byte + 2) = (byte)imgProcessed[count + 2];
                        *(Byte + 3) = (byte)imgProcessed[count + 3];
                        count += 4;
                    }
                }
            }
            progressBar.Owner.Invoke((Action)progressBar.PerformStep);
        }

        //Unlock image
        image.UnlockBits(imageData);
    }
4

1 に答える 1

1

OpenCL ドライバー/デバイスのメモリ割り当て制限に達した可能性があります。clGetDeviceInfoによって返される値を確認してください。1 つのメモリ オブジェクトのサイズには制限があります。OpenCL ドライバーは、割り当てられたすべてのメモリ オブジェクトの合計サイズがデバイスのメモリ サイズを超えることを許可する場合があり、必要に応じてそれらをホスト メモリとの間でコピーします。

大きな画像を処理するには、画像を小さな断片に分割し、別々に処理する必要がある場合があります。

于 2012-09-18T18:18:22.283 に答える