private void InitVendorFeatures() { // Check major vendor features if (CLAPI.GetDeviceInfo( DeviceId, CLDeviceInfoType.CL_DEVICE_WARP_SIZE_NV, out int warpSize) == CLError.CL_SUCCESS) { // Nvidia platform WarpSize = warpSize; Vendor = CLAcceleratorVendor.Nvidia; int major = CLAPI.GetDeviceInfo <int>( DeviceId, CLDeviceInfoType.CL_DEVICE_COMPUTE_CAPABILITY_MAJOR_NV); int minor = CLAPI.GetDeviceInfo <int>( DeviceId, CLDeviceInfoType.CL_DEVICE_COMPUTE_CAPABILITY_MINOR_NV); if (major < 7 || major == 7 && minor < 5) { MaxNumThreadsPerMultiprocessor *= 2; } } else if (CLAPI.GetDeviceInfo( DeviceId, CLDeviceInfoType.CL_DEVICE_WAVEFRONT_WIDTH_AMD, out int wavefrontSize) == CLError.CL_SUCCESS) { // AMD platform WarpSize = wavefrontSize; Vendor = CLAcceleratorVendor.AMD; } else { Vendor = VendorName.Contains(CLAcceleratorVendor.Intel.ToString()) ? CLAcceleratorVendor.Intel : CLAcceleratorVendor.Other; // Compile dummy kernel to resolve additional information CLException.ThrowIfFailed(CLKernel.LoadKernel( this, DummyKernelSource, out IntPtr programPtr, out IntPtr kernelPtr)); try { // Resolve information WarpSize = CLAPI.GetKernelWorkGroupInfo <IntPtr>( kernelPtr, DeviceId, CLKernelWorkGroupInfoType.CL_KERNEL_PREFERRED_WORK_GROUP_SIZE_MULTIPLE).ToInt32(); } finally { CLException.ThrowIfFailed( CLAPI.ReleaseKernel(kernelPtr) | CLAPI.ReleaseProgram(programPtr)); } } }
/// <summary cref="DisposeBase.Dispose(bool)"/> protected override void Dispose(bool disposing) { CLException.ThrowIfFailed( CLAPI.ReleaseKernel(kernelPtr) | CLAPI.ReleaseProgram(programPtr)); programPtr = IntPtr.Zero; kernelPtr = IntPtr.Zero; }
private void InitSubGroupSupport(CLAcceleratorId acceleratorId) { // Check sub group support if (!(SubGroupSupport = acceleratorId.HasAnyExtension(SubGroupExtensions))) { return; } // Verify support using a simple kernel if (CLKernel.LoadKernel( this, DummySubGroupKernelSource, CVersion, out IntPtr programPtr, out IntPtr kernelPtr, out var _) == CLError.CL_SUCCESS) { // Some drivers return an internal handler delegate // that crashes during invocation instead of telling that the // sub-group feature is not supported try { var localGroupSizes = new IntPtr[] { new IntPtr(MaxNumThreadsPerGroup) }; SubGroupSupport = acceleratorId.TryGetKernelSubGroupInfo( kernelPtr, DeviceId, CLKernelSubGroupInfoType .CL_KERNEL_MAX_SUB_GROUP_SIZE_FOR_NDRANGE_KHR, localGroupSizes, out IntPtr subGroupSize); WarpSize = subGroupSize.ToInt32(); } catch (AccessViolationException) { // This exception can be raised due to driver issues // on several platforms -> we will just disable sub-group // support for these platforms SubGroupSupport = false; } finally { CLException.ThrowIfFailed( CLAPI.ReleaseKernel(kernelPtr)); CLException.ThrowIfFailed( CLAPI.ReleaseProgram(programPtr)); } } }
/// <summary> /// Loads the given OpenCL kernel. /// </summary> /// <param name="accelerator">The associated accelerator.</param> /// <param name="source">The OpenCL source code.</param> /// <param name="version">The OpenCL C version.</param> /// <param name="programPtr">The created program pointer.</param> /// <param name="kernelPtr">The created kernel pointer.</param> /// <param name="errorLog">The error log (if any).</param> /// <returns>True, if the program and the kernel could be loaded successfully.</returns> internal static CLError LoadKernel( CLAccelerator accelerator, string source, CLCVersion version, out IntPtr programPtr, out IntPtr kernelPtr, out string errorLog) { errorLog = null; kernelPtr = IntPtr.Zero; var programError = CLAPI.CreateProgram( accelerator.ContextPtr, source, out programPtr); if (programError != CLError.CL_SUCCESS) { return(programError); } // Specify the OpenCL C version. string options = "-cl-std=" + version.ToString(); var buildError = CLAPI.BuildProgram( programPtr, accelerator.DeviceId, options); if (buildError != CLError.CL_SUCCESS) { CLException.ThrowIfFailed( CLAPI.GetProgramBuildLog( programPtr, accelerator.DeviceId, out errorLog)); CLException.ThrowIfFailed( CLAPI.ReleaseProgram(programPtr)); programPtr = IntPtr.Zero; return(buildError); } return(CLAPI.CreateKernel( programPtr, CLCompiledKernel.EntryName, out kernelPtr)); }
/// <summary> /// Loads the given OpenCL kernel. /// </summary> /// <param name="accelerator">The associated accelerator.</param> /// <param name="source">The OpenCL source code.</param> /// <param name="programPtr">The created program pointer.</param> /// <param name="kernelPtr">The created kernel pointer.</param> /// <returns>True, if the program and the kernel could be loaded successfully.</returns> internal static CLError LoadKernel( CLAccelerator accelerator, string source, out IntPtr programPtr, out IntPtr kernelPtr) { kernelPtr = IntPtr.Zero; var error = CLAPI.CreateProgram( accelerator.ContextPtr, source, out programPtr); if (error != CLError.CL_SUCCESS) { return(error); } // TODO: OpenCL compiler options string options = string.Empty; error |= CLAPI.BuildProgram( programPtr, accelerator.DeviceId, options); error |= CLAPI.CreateKernel( programPtr, CLCompiledKernel.EntryName, out kernelPtr); if (error != CLError.CL_SUCCESS) { CLException.ThrowIfFailed( CLAPI.ReleaseProgram(programPtr)); programPtr = IntPtr.Zero; } return(error); }