Cudafy.NET - CUDA.NET 异常 ErrorInvalidValue

Cudafy.NET - CUDA.NET exception ErrorInvalidValue

我正在使用 Cudafy.NET 在 GPU 上执行图像处理。我已经设置了 class 以及第一个函数(CPU 上的 PerformBarrelCorrection 运行)来设置多个线程来为图像中的每个像素执行逻辑计算。

但是每次我在 GPU 上启动函数时都会抛出异常:

An exception of type 'Cudafy.Host.CudafyHostException' occurred in Cudafy.NET.dll but was not handled in user code

Additional information: CUDA.NET exception: ErrorInvalidValue.

这里是 class 的完整注释,以显示引发异常的行。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Cudafy;
using Cudafy.Host;
using Cudafy.Translator;
using System.Drawing;
using System.IO;

namespace AForgeTrial
{
    class GPUProcessing
    {
        public CudafyModule km;
        public GPGPU gpu;

        public GPUProcessing() {
            km = CudafyTranslator.Cudafy();
            gpu = CudafyHost.GetDevice(CudafyModes.Target, CudafyModes.DeviceId);
            gpu.LoadModule(km);
        }

        public Bitmap PerformBarrelCorrection(Bitmap source, double strength, float zoom, int imageWidth, int imageHeight)
        {
            byte[] bmp = ImageToByteArray2(source);

            int halfWidth = imageWidth / 2;
            int halfHeight = imageHeight / 2;

            double correctionRadius = Math.Sqrt(((imageWidth * imageWidth) + (imageHeight * imageHeight)) / strength);

            byte[] dev_src_bmp = gpu.CopyToDevice(bmp);
            byte[] dst_bmp = new byte[bmp.Length];
            byte[] dev_dst_bmp = gpu.Allocate<byte>(dst_bmp);

            double[] correctPass = new double[1];
            correctPass[0] = correctionRadius;
            double[] dev_correctionRadius = gpu.CopyToDevice<double>(correctPass);

            float[] zoomPass = new float[1];
            zoomPass[0] = zoom;
            float[] dev_zoom = gpu.CopyToDevice<float>(zoomPass);

            int[] halfWidthPass = new int[1];
            halfWidthPass[0] = halfWidth;
            int[] dev_halfWidth = gpu.CopyToDevice<int>(halfWidthPass);

            int[] halfHeightPass = new int[1];
            halfHeightPass[0] = imageHeight;
            int[] dev_halfHeight = gpu.CopyToDevice<int>(halfHeightPass);

            //int blksize = ((bmp.Length / 3) / 128) + 1;

            // EXCEPTION HAPPENS ON THE LINE BELOW
            gpu.Launch((bmp.Length / 3), 1).BarrelCorrectionSingleOperation(dev_src_bmp, dev_dst_bmp, dev_correctionRadius, dev_zoom, dev_halfWidth, dev_halfHeight);

            gpu.CopyFromDevice(dev_dst_bmp, dst_bmp);

            // Convert dst_bmp to Bitmap and return it
            Bitmap result;
            using (MemoryStream ms = new MemoryStream(dst_bmp))
            {
                result = new Bitmap(ms);
            }
            return result;
        }

        [Cudafy]
        public static void BarrelCorrectionSingleOperation(GThread thread, byte[] src_bmp, byte[] dst_bmp, double[] correctionRadius, float[] zoom, int[] halfWidth, int[] halfHeight)
        { 
            // Move a single byte from source to destination or fill if required
        }

        public static byte[] ImageToByteArray(Bitmap img)
        {
            ImageConverter converter = new ImageConverter();
            return (byte[])converter.ConvertTo(img, typeof(byte[]));
        }

        public static byte[] ImageToByteArray2(Bitmap img)
        {
            byte[] byteArray = new byte[0];
            using (MemoryStream stream = new MemoryStream())
            {
                img.Save(stream, System.Drawing.Imaging.ImageFormat.Png);
                stream.Close();

                byteArray = stream.ToArray();
            }
            return byteArray;
        }

        public void Close() {
            gpu.FreeAll();
        }
    }
}

有人知道这件事吗??提前致谢。

为任何感兴趣的人解决了我自己的问题,尽管它非常小众,但我的代码充满了漏洞。这成功地使用 Cudafy 执行了实时镜头校正。

public void PerformBarrelCorrection(double strength, float zoom)
        {
            CheckIsSet();

            int halfWidth = Width / 2;
            int halfHeight = Height / 2;

            double correctionRadius = Math.Sqrt(((Width * Width) + (Height * Height)) / strength);

            _gpu.Launch(Width, Height).BarrelCorrectionSingleOperation(_gdata.SourceImage, _gdata.ResultImage, correctionRadius, zoom, halfWidth, halfHeight);

        }

        [Cudafy]
        public static void BarrelCorrectionSingleOperation(GThread thread, byte[] src_bmp, byte[] dst_bmp, double correctionRadius, float zoom, int halfWidth, int halfHeight)
        {
            // Move a single byte from source to destination or fill if required
            int x = thread.blockIdx.x;
            int y = thread.threadIdx.x;

            int newX = x - halfWidth;
            int newY = y - halfHeight;

            double distance = Math.Sqrt((newX * newX) + (newY * newY));
            double r = distance / correctionRadius;

            double theta;
            if (r == 0)
            {
                theta = 1;
            }
            else
            {
                theta = Math.Atan(r) / r;
            }

            int sourceX = (int)(halfWidth + theta * newX * zoom);
            int sourceY = (int)(halfHeight + theta * newY * zoom);

            dst_bmp[(y * ((halfWidth * 2) * 4)) + (x * 4)] = src_bmp[(sourceY * ((halfWidth * 2) * 4)) + (sourceX * 4)];
            dst_bmp[(y * (((halfWidth * 2) * 4)) + (x * 4)) + 1] = src_bmp[((sourceY * ((halfWidth * 2) * 4)) + (sourceX * 4)) + 1];
            dst_bmp[(y * (((halfWidth * 2) * 4)) + (x * 4)) + 2] = src_bmp[((sourceY * ((halfWidth * 2) * 4)) + (sourceX * 4)) + 2];
            dst_bmp[(y * (((halfWidth * 2) * 4)) + (x * 4)) + 3] = src_bmp[((sourceY * ((halfWidth * 2) * 4)) + (sourceX * 4)) + 3];
        }