Skip to content

Commit

Permalink
Use static logging
Browse files Browse the repository at this point in the history
  • Loading branch information
HamletTanyavong committed Dec 21, 2024
1 parent 5619c59 commit f4a622d
Show file tree
Hide file tree
Showing 4 changed files with 66 additions and 65 deletions.
28 changes: 20 additions & 8 deletions src/Mathematics.NET/GPU/OpenCL/Context.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
namespace Mathematics.NET.GPU.OpenCL;

/// <summary>Represents an OpenCL context.</summary>
public sealed class Context : IOpenCLObject
public sealed partial class Context : IOpenCLObject
{
// Api.
private readonly CL _cl;
Expand All @@ -44,18 +44,24 @@ public unsafe Context(ILogger<OpenCLService> 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()
Expand All @@ -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;
Expand Down
13 changes: 6 additions & 7 deletions src/Mathematics.NET/GPU/OpenCL/Kernel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
namespace Mathematics.NET.GPU.OpenCL;

/// <summary>Represents an OpenCL kernel.</summary>
public sealed class Kernel : IOpenCLObject
public sealed partial class Kernel : IOpenCLObject
{
private CL _cl;
private ILogger<OpenCLService> _logger;
Expand All @@ -46,14 +46,10 @@ public unsafe Kernel(ILogger<OpenCLService> 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()
Expand All @@ -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;
Expand Down
81 changes: 35 additions & 46 deletions src/Mathematics.NET/GPU/OpenCL/OpenCLService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
// </copyright>

#pragma warning disable IDE0032
#pragma warning disable IDE0058

using System.Runtime.InteropServices;
using Microsoft.Extensions.Logging;
Expand All @@ -34,7 +35,7 @@
namespace Mathematics.NET.GPU.OpenCL;

/// <summary>Represents an Mathematics.NET OpenCL service.</summary>
public sealed class OpenCLService : IComputeService
public sealed partial class OpenCLService : IComputeService
{
/// <summary>A class containing names of common vendors.</summary>
public static class Vendors
Expand All @@ -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<OpenCLService> _logger;
private CL _cl;

Expand Down Expand Up @@ -85,9 +83,7 @@ public unsafe OpenCLService(ILogger<OpenCLService> logger, string vendor, Func<D
if (platforms.FirstOrDefault(x => x.Vendor == vendor) is Platform platform)
{
_platform = platform;
#if DEBUG
_logger.LogDebug("Platform vendor: {Vendor}.", _platform.Vendor);
#endif
LogPlatformVendor(_platform.Vendor);
}
else
{
Expand All @@ -101,12 +97,11 @@ public unsafe OpenCLService(ILogger<OpenCLService> logger, string vendor, Func<D
_devices = _context.GetDevices(filter, useFirst).ToArray();
if (_devices.Length == 0)
throw new Exception("There are no devices available after filtering.");
#if DEBUG

for (int i = 0; i < _devices.Length; i++)
{
_logger.LogDebug("Using the device at index {Index} with name: {DeviceName}.", i, _devices.Span[i].Name);
LogDeviceUsed(i, _devices.Span[i].Name);
}
#endif

// OpenCL program.
_program = new Program(_logger, _cl, _context, _devices.Span, options);
Expand Down Expand Up @@ -136,6 +131,18 @@ public void Dispose()
_cl.Dispose();
}

[LoggerMessage(LogLevel.Information, "Platform vendor: {Vendor}.")]
private partial void LogPlatformVendor(string vendor);

[LoggerMessage(LogLevel.Information, "Using the device at index, {Index}, with name, {Name}.")]
private partial void LogDeviceUsed(int index, string name);

[LoggerMessage(LogLevel.Error, "Unable to set arguments for the kernel {Kernel}.")]
private partial void CouldNotSetKernelArguments(string kernel);

[LoggerMessage(LogLevel.Error, "Unable to enqueue the n-dimensional range kernel {Kernel}.")]
private partial void CouldNotEnqueueNDRangeKernel(string kernel);

public ReadOnlySpan<Device> Devices => _devices.Span;

public Program Program => _program;
Expand All @@ -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);

Expand Down Expand Up @@ -200,18 +204,15 @@ public unsafe ReadOnlySpan<Complex> 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);

Expand Down Expand Up @@ -250,18 +251,15 @@ public unsafe ReadOnlySpan2D<Complex> 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);

Expand Down Expand Up @@ -302,18 +300,15 @@ public unsafe ReadOnlySpan2D<Real> 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);

Expand All @@ -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);

Expand Down Expand Up @@ -378,18 +370,15 @@ public unsafe ReadOnlySpan<Real> 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);

Expand Down
9 changes: 5 additions & 4 deletions src/Mathematics.NET/GPU/OpenCL/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
namespace Mathematics.NET.GPU.OpenCL;

/// <summary>Represents an OpenCL program.</summary>
public sealed class Program : IOpenCLObject
public sealed partial class Program : IOpenCLObject
{
private readonly CL _cl;
private readonly ILogger<OpenCLService> _logger;
Expand Down Expand Up @@ -72,10 +72,8 @@ public unsafe Program(ILogger<OpenCLService> 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())
Expand Down Expand Up @@ -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;
Expand Down

0 comments on commit f4a622d

Please sign in to comment.