Cudafy.NET - исключение CUDA.NET ErrorInvalidValue
Я использую Cudafy.NET для выполнения обработки изображений на GPU. Я настроил свой класс вместе с первой функцией (PerformBarrelCorrection, запущенной на CPU), чтобы настроить несколько потоков для выполнения логического вычисления для каждого пикселя в изображении.
Однако каждый раз, когда я запускаю функцию на графическом процессоре, она выдает исключение:
Исключение типа "Cudafy.Host.CudafyHostException" произошло в Cudafy.NET.dll, но не было обработано в коде пользователя
Дополнительная информация: CUDA.NET исключение: ErrorInvalidValue.
Здесь весь класс прокомментирован, чтобы показать строку, в которую выдается исключение.
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();
}
}
}
Кто-нибудь знает что-нибудь об этом?? Заранее спасибо.
1 ответ
Решил мой собственный вопрос для всех, кто заинтересовался, хотя в самой его нише мой код был полон дыр. Он успешно выполняет коррекцию объектива в режиме реального времени с помощью 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];
}