/// <summary> /// Detects OpenCL devices. /// </summary> /// <param name="predicate"> /// The predicate to include a given device. /// </param> /// <param name="registry">The registry to add all devices to.</param> private static void GetDevicesInternal( Predicate <CLDevice> predicate, DeviceRegistry registry) { var devices = new IntPtr[MaxNumDevicesPerPlatform]; // Resolve all platforms if (!CurrentAPI.IsSupported || CurrentAPI.GetNumPlatforms(out int numPlatforms) != CLError.CL_SUCCESS || numPlatforms < 1) { return; } var platforms = new IntPtr[numPlatforms]; if (CurrentAPI.GetPlatforms(platforms, ref numPlatforms) != CLError.CL_SUCCESS) { return; } foreach (var platform in platforms) { // Resolve all devices int numDevices = devices.Length; Array.Clear(devices, 0, numDevices); if (CurrentAPI.GetDevices( platform, CLDeviceType.CL_DEVICE_TYPE_ALL, devices, out numDevices) != CLError.CL_SUCCESS) { continue; } for (int i = 0; i < numDevices; ++i) { // Resolve device and ignore invalid devices var device = devices[i]; if (device == IntPtr.Zero) { continue; } // Check for available device if (CurrentAPI.GetDeviceInfo <int>( device, CLDeviceInfoType.CL_DEVICE_AVAILABLE) == 0) { continue; } var desc = new CLDevice(platform, device); registry.Register(desc, predicate); } } }
/// <summary> /// Enables all OpenCL devices. /// </summary> /// <param name="builder">The builder instance.</param> /// <param name="predicate"> /// The predicate to include a given device. /// </param> /// <returns>The updated builder instance.</returns> public static Context.Builder OpenCL( this Context.Builder builder, Predicate <CLDevice> predicate) { CLDevice.GetDevices( predicate, builder.DeviceRegistry); return(builder); }
/// <summary> /// Initializes support for sub groups. /// </summary> /// <param name="acceleratorId">The current accelerator id.</param> private void InitSubGroupSupport(CLDevice acceleratorId) { // Check sub group support Capabilities.SubGroups = acceleratorId.HasAnyExtension(SubGroupExtensions); if (!Capabilities.SubGroups) { return; } // Verify support using a simple kernel if (CLKernel.LoadKernel( this, DummyKernelName, 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) }; Capabilities.SubGroups = 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 Capabilities.SubGroups = false; } finally { CLException.ThrowIfFailed( CurrentAPI.ReleaseKernel(kernelPtr)); CLException.ThrowIfFailed( CurrentAPI.ReleaseProgram(programPtr)); } } }
/// <summary> /// Constructs a new OpenCL accelerator. /// </summary> /// <param name="context">The ILGPU context.</param> /// <param name="description">The accelerator description.</param> internal CLAccelerator(Context context, CLDevice description) : base(context, description) { Backends.Backend.EnsureRunningOnNativePlatform(); // Create new context CLException.ThrowIfFailed( CurrentAPI.CreateContext(DeviceId, out var contextPtr)); NativePtr = contextPtr; Bind(); DefaultStream = CreateStreamInternal(); InitVendorFeatures(); InitSubGroupSupport(description); Init(new CLBackend(Context, Capabilities, Vendor)); }
/// <summary> /// Constructs a new OpenCL accelerator. /// </summary> /// <param name="context">The ILGPU context.</param> /// <param name="description">The accelerator description.</param> internal CLAccelerator(Context context, CLDevice description) : base(context, description) { Backends.Backend.EnsureRunningOnNativePlatform(); if (!description.Capabilities.GenericAddressSpace) { throw CLCapabilityContext.GetNotSupportedGenericAddressSpaceException(); } // Create new context CLException.ThrowIfFailed( CurrentAPI.CreateContext(DeviceId, out var contextPtr)); NativePtr = contextPtr; Bind(); DefaultStream = CreateStreamInternal(); InitVendorFeatures(); InitSubGroupSupport(description); Init(new CLBackend(Context, Capabilities, Vendor, CLStdVersion)); }