diff --git a/src/Mathematics.NET/GPU/OpenCL/Context.cs b/src/Mathematics.NET/GPU/OpenCL/Context.cs
index bac80cdd..b4cbe41f 100644
--- a/src/Mathematics.NET/GPU/OpenCL/Context.cs
+++ b/src/Mathematics.NET/GPU/OpenCL/Context.cs
@@ -33,7 +33,7 @@
namespace Mathematics.NET.GPU.OpenCL;
/// Represents an OpenCL context.
-public sealed class Context : IOpenCLObject
+public sealed partial class Context : IOpenCLObject
{
// Api.
private readonly CL _cl;
@@ -44,18 +44,24 @@ public unsafe Context(ILogger logger, CL cl, Platform platform)
_cl = cl;
_logger = logger;
- // Attempt to create a GPU context. If that does not work, attempt to create a CPU context.
- var contextProperties = stackalloc nint[3] { (nint)ContextProperties.Platform, platform.Handle, 0 };
- Handle = _cl.CreateContextFromType(contextProperties, DeviceType.Gpu, null, null, out var error);
- if (error != (int)ErrorCodes.Success)
+ try
{
- _logger.LogDebug("Unable to create GPU context; attempting to create CPU context instead.");
- Handle = _cl.CreateContextFromType(contextProperties, DeviceType.Cpu, null, null, out error);
+ // Attempt to create a GPU context. If that does not work, attempt to create a CPU context.
+ var contextProperties = stackalloc nint[3] { (nint)ContextProperties.Platform, platform.Handle, 0 };
+ Handle = _cl.CreateContextFromType(contextProperties, DeviceType.Gpu, null, null, out var error);
if (error != (int)ErrorCodes.Success)
{
- throw new Exception("Unable to create context on either the GPU or CPU.");
+ CouldNotCreateGPUContext();
+ Handle = _cl.CreateContextFromType(contextProperties, DeviceType.Cpu, null, null, out error);
+ if (error != (int)ErrorCodes.Success)
+ throw new Exception("Unable to create context on either the GPU or CPU.");
}
}
+ catch (Exception ex)
+ {
+ CouldNotCreateContext(ex);
+ throw;
+ }
}
public void Dispose()
@@ -67,6 +73,12 @@ public void Dispose()
}
}
+ [LoggerMessage(LogLevel.Warning, "Unable to create a GPU context; attempting to create a CPU context instead.")]
+ private partial void CouldNotCreateGPUContext();
+
+ [LoggerMessage(LogLevel.Error, "Unable to create a context on either the GPU or CPU.")]
+ private partial void CouldNotCreateContext(Exception ex);
+
public nint Handle { get; private set; }
public bool IsValidInstance => Handle != 0;
diff --git a/src/Mathematics.NET/GPU/OpenCL/Kernel.cs b/src/Mathematics.NET/GPU/OpenCL/Kernel.cs
index 7a3e50d0..311009df 100644
--- a/src/Mathematics.NET/GPU/OpenCL/Kernel.cs
+++ b/src/Mathematics.NET/GPU/OpenCL/Kernel.cs
@@ -33,7 +33,7 @@
namespace Mathematics.NET.GPU.OpenCL;
/// Represents an OpenCL kernel.
-public sealed class Kernel : IOpenCLObject
+public sealed partial class Kernel : IOpenCLObject
{
private CL _cl;
private ILogger _logger;
@@ -46,14 +46,10 @@ public unsafe Kernel(ILogger logger, CL cl, Program program, stri
_logger = logger;
Name = name;
-
Handle = _cl.CreateKernel(program.Handle, name, out var error);
-#if DEBUG
+
if (error != (int)ErrorCodes.Success)
- {
- _logger.LogDebug("Unable to create kernel.");
- }
-#endif
+ CouldNotCreateKernel(name);
}
public void Dispose()
@@ -65,6 +61,9 @@ public void Dispose()
}
}
+ [LoggerMessage(LogLevel.Error, "Unable to create the kernel {Kernel}.")]
+ private partial void CouldNotCreateKernel(string kernel);
+
public nint Handle { get; private set; }
public bool IsValidInstance => Handle != 0;
diff --git a/src/Mathematics.NET/GPU/OpenCL/OpenCLService.cs b/src/Mathematics.NET/GPU/OpenCL/OpenCLService.cs
index 5aa9c18b..a6190072 100644
--- a/src/Mathematics.NET/GPU/OpenCL/OpenCLService.cs
+++ b/src/Mathematics.NET/GPU/OpenCL/OpenCLService.cs
@@ -26,6 +26,7 @@
//
#pragma warning disable IDE0032
+#pragma warning disable IDE0058
using System.Runtime.InteropServices;
using Microsoft.Extensions.Logging;
@@ -34,7 +35,7 @@
namespace Mathematics.NET.GPU.OpenCL;
/// Represents an Mathematics.NET OpenCL service.
-public sealed class OpenCLService : IComputeService
+public sealed partial class OpenCLService : IComputeService
{
/// A class containing names of common vendors.
public static class Vendors
@@ -44,9 +45,6 @@ public static class Vendors
public const string NVIDIA = "NVIDIA Corporation";
}
- private const string s_setKernelArgError = "Unable to set arguments for the kernel {Kernel}.";
- private const string s_enqueueNDRangeKernelError = "Problem enqueueing NDRange kernel.";
-
private ILogger _logger;
private CL _cl;
@@ -85,9 +83,7 @@ public unsafe OpenCLService(ILogger logger, string vendor, Func x.Vendor == vendor) is Platform platform)
{
_platform = platform;
-#if DEBUG
- _logger.LogDebug("Platform vendor: {Vendor}.", _platform.Vendor);
-#endif
+ LogPlatformVendor(_platform.Vendor);
}
else
{
@@ -101,12 +97,11 @@ public unsafe OpenCLService(ILogger logger, string vendor, Func Devices => _devices.Span;
public Program Program => _program;
@@ -161,18 +168,15 @@ public unsafe void CompVecMulScalar(Device device, nuint globalWorkSize, nuint l
var kernel = _program.Kernels["comp_vec_mul_scalar_overwrite"].Handle;
var error = _cl.SetKernelArg(kernel, 0, (nuint)sizeof(nint), &vectorBuffer);
error |= _cl.SetKernelArg(kernel, 1, (nuint)sizeof(Complex), in scalar);
-#if DEBUG
if (error != (int)ErrorCodes.Success)
- _logger.LogDebug(s_setKernelArgError, _program.Kernels["comp_vec_mul_scalar_overwrite"].Name);
-#endif
+ CouldNotSetKernelArguments("comp_vec_mul_scalar_overwrite");
// Enqueue NDRange kernel.
using var commandQueue = _context.CreateCommandQueue(device, CommandQueueProperties.None);
error = _cl.EnqueueNdrangeKernel(commandQueue.Handle, kernel, 1, null, &globalWorkSize, &localWorkSize, 0, null, null);
-#if DEBUG
if (error != (int)ErrorCodes.Success)
- _logger.LogDebug(s_enqueueNDRangeKernelError);
-#endif
+ CouldNotEnqueueNDRangeKernel("comp_vec_mul_scalar_overwrite");
+
// Enqueue read buffer.
_cl.EnqueueReadBuffer(commandQueue.Handle, vectorBuffer, true, 0, (nuint)(sizeof(Complex) * vector.Length), pVector, 0, null, null);
@@ -200,18 +204,15 @@ public unsafe ReadOnlySpan CompVecMulScalar(Device device, nuint global
var error = _cl.SetKernelArg(kernel, 0, (nuint)sizeof(nint), &vectorBuffer);
error |= _cl.SetKernelArg(kernel, 1, (nuint)sizeof(Complex), in scalar);
error |= _cl.SetKernelArg(kernel, 2, (nuint)sizeof(nint), &resultBuffer);
-#if DEBUG
if (error != (int)ErrorCodes.Success)
- _logger.LogDebug(s_setKernelArgError, _program.Kernels["comp_vec_mul_scalar"].Name);
-#endif
+ CouldNotSetKernelArguments("comp_vec_mul_scalar");
// Enqueue NDRange kernel.
using var commandQueue = _context.CreateCommandQueue(device, CommandQueueProperties.None);
error = _cl.EnqueueNdrangeKernel(commandQueue.Handle, kernel, 1, null, &globalWorkSize, &localWorkSize, 0, null, null);
-#if DEBUG
if (error != (int)ErrorCodes.Success)
- _logger.LogDebug(s_enqueueNDRangeKernelError);
-#endif
+ CouldNotEnqueueNDRangeKernel("comp_vec_mul_scalar");
+
// Enqueue read buffer.
_cl.EnqueueReadBuffer(commandQueue.Handle, resultBuffer, true, 0, (nuint)(sizeof(Complex) * length), pResult, 0, null, null);
@@ -250,18 +251,15 @@ public unsafe ReadOnlySpan2D CompMatMul(Device device, WorkSize2D globa
error |= _cl.SetKernelArg(kernel, 1, (nuint)sizeof(nint), &rightBuffer);
error |= _cl.SetKernelArg(kernel, 2, sizeof(int), &k);
error |= _cl.SetKernelArg(kernel, 3, (nuint)sizeof(nint), &resultBuffer);
-#if DEBUG
if (error != (int)ErrorCodes.Success)
- _logger.LogDebug(s_setKernelArgError, _program.Kernels["comp_mat_mul"].Name);
-#endif
+ CouldNotSetKernelArguments("comp_mat_mul");
// Enqueue NDRange kernel.
using var commandQueue = _context.CreateCommandQueue(device, CommandQueueProperties.None);
error = _cl.EnqueueNdrangeKernel(commandQueue.Handle, kernel, 2, null, (nuint*)&globalWorkSize, (nuint*)&localWorkSize, 0, null, null);
-#if DEBUG
if (error != (int)ErrorCodes.Success)
- _logger.LogDebug(s_enqueueNDRangeKernelError);
-#endif
+ CouldNotEnqueueNDRangeKernel("comp_mat_mul");
+
// Enqueue read buffer.
_cl.EnqueueReadBuffer(commandQueue.Handle, resultBuffer, true, 0, (nuint)(sizeof(Complex) * result.Length), pResult, 0, null, null);
@@ -302,18 +300,15 @@ public unsafe ReadOnlySpan2D MatMul(Device device, WorkSize2D globalWorkSi
error |= _cl.SetKernelArg(kernel, 1, (nuint)sizeof(nint), &rightBuffer);
error |= _cl.SetKernelArg(kernel, 2, sizeof(int), &k);
error |= _cl.SetKernelArg(kernel, 3, (nuint)sizeof(nint), &resultBuffer);
-#if DEBUG
if (error != (int)ErrorCodes.Success)
- _logger.LogDebug(s_setKernelArgError, _program.Kernels["mat_mul"].Name);
-#endif
+ CouldNotSetKernelArguments("mat_mul");
// Enqueue NDRange kernel.
using var commandQueue = _context.CreateCommandQueue(device, CommandQueueProperties.None);
error = _cl.EnqueueNdrangeKernel(commandQueue.Handle, kernel, 2, null, (nuint*)&globalWorkSize, (nuint*)&localWorkSize, 0, null, null);
-#if DEBUG
if (error != (int)ErrorCodes.Success)
- _logger.LogDebug(s_enqueueNDRangeKernelError);
-#endif
+ CouldNotEnqueueNDRangeKernel("mat_mul");
+
// Enqueue read buffer.
_cl.EnqueueReadBuffer(commandQueue.Handle, resultBuffer, true, 0, (nuint)(sizeof(Real) * result.Length), pResult, 0, null, null);
@@ -339,18 +334,15 @@ public unsafe void VecMulScalar(Device device, nuint globalWorkSize, nuint local
var kernel = _program.Kernels["vec_mul_scalar_overwrite"].Handle;
var error = _cl.SetKernelArg(kernel, 0, (nuint)sizeof(nint), &vectorBuffer);
error |= _cl.SetKernelArg(kernel, 1, (nuint)sizeof(Real), in scalar);
-#if DEBUG
if (error != (int)ErrorCodes.Success)
- _logger.LogDebug(s_setKernelArgError, _program.Kernels["vec_mul_scalar_overwrite"].Name);
-#endif
+ CouldNotSetKernelArguments("vec_mul_scalar_overwrite");
// Enqueue NDRange kernel.
using var commandQueue = _context.CreateCommandQueue(device, CommandQueueProperties.None);
error = _cl.EnqueueNdrangeKernel(commandQueue.Handle, kernel, 1, null, &globalWorkSize, &localWorkSize, 0, null, null);
-#if DEBUG
if (error != (int)ErrorCodes.Success)
- _logger.LogDebug(s_enqueueNDRangeKernelError);
-#endif
+ CouldNotEnqueueNDRangeKernel("vec_mul_scalar_overwrite");
+
// Enqueue read buffer.
_cl.EnqueueReadBuffer(commandQueue.Handle, vectorBuffer, true, 0, (nuint)(sizeof(Real) * vector.Length), pVector, 0, null, null);
@@ -378,18 +370,15 @@ public unsafe ReadOnlySpan VecMulScalar(Device device, nuint globalWorkSiz
var error = _cl.SetKernelArg(kernel, 0, (nuint)sizeof(nint), &vectorBuffer);
error |= _cl.SetKernelArg(kernel, 1, (nuint)sizeof(Real), &scalar);
error |= _cl.SetKernelArg(kernel, 2, (nuint)sizeof(nint), &resultBuffer);
-#if DEBUG
if (error != (int)ErrorCodes.Success)
- _logger.LogDebug(s_setKernelArgError, _program.Kernels["vec_mul_scalar"].Name);
-#endif
+ CouldNotSetKernelArguments("vec_mul_scalar");
// Enqueue NDRange kernel.
using var commandQueue = _context.CreateCommandQueue(device, CommandQueueProperties.None);
error = _cl.EnqueueNdrangeKernel(commandQueue.Handle, kernel, 1, null, &globalWorkSize, &localWorkSize, 0, null, null);
-#if DEBUG
if (error != (int)ErrorCodes.Success)
- _logger.LogDebug(s_enqueueNDRangeKernelError);
-#endif
+ CouldNotEnqueueNDRangeKernel("vec_mul_scalar");
+
// Enqueue read buffer.
_cl.EnqueueReadBuffer(commandQueue.Handle, resultBuffer, true, 0, (nuint)(sizeof(Real) * length), pResult, 0, null, null);
diff --git a/src/Mathematics.NET/GPU/OpenCL/Program.cs b/src/Mathematics.NET/GPU/OpenCL/Program.cs
index fe870eb9..40eef756 100644
--- a/src/Mathematics.NET/GPU/OpenCL/Program.cs
+++ b/src/Mathematics.NET/GPU/OpenCL/Program.cs
@@ -34,7 +34,7 @@
namespace Mathematics.NET.GPU.OpenCL;
/// Represents an OpenCL program.
-public sealed class Program : IOpenCLObject
+public sealed partial class Program : IOpenCLObject
{
private readonly CL _cl;
private readonly ILogger _logger;
@@ -72,10 +72,8 @@ public unsafe Program(ILogger logger, CL cl, Context context, Rea
fixed (nuint* pCodeLengths = codeLengths)
{
Handle = _cl.CreateProgramWithSource(context.Handle, (uint)code.Length, code, pCodeLengths, out var error);
-#if DEBUG
if (error != (int)ErrorCodes.Success)
- _logger.LogDebug("Unable to create the program from source.");
-#endif
+ CouldNotCreateProgram();
}
fixed (nint* pDevices = devices.ToArray().Select(x => x.Handle).ToArray())
@@ -115,6 +113,9 @@ public void Dispose()
}
}
+ [LoggerMessage(LogLevel.Error, "Unable to create the program from source.")]
+ private partial void CouldNotCreateProgram();
+
public nint Handle { get; private set; }
public bool IsValidInstance => Handle != 0;