internal OpenCLDevice(OpenCLPlatform platform, CLDeviceHandle handle) { Handle = handle; SetID(Handle.Value); this.Platform = platform; }
/// <summary> /// Creates a new <see cref="OpenCLContext"/> on all the <see cref="OpenCLDevice"/>s that match the specified <see cref="OpenCLDeviceTypes"/>. /// </summary> /// <param name="deviceType"> A bit-field that identifies the type of <see cref="OpenCLDevice"/> to associate with the <see cref="OpenCLContext"/>. </param> /// <param name="properties"> A <see cref="OpenCLContextPropertyList"/> of the <see cref="OpenCLContext"/>. </param> /// <param name="notify"> A delegate instance that refers to a notification routine. This routine is a callback function that will be used by the OpenCL implementation to report information on errors that occur in the <see cref="OpenCLContext"/>. The callback function may be called asynchronously by the OpenCL implementation. It is the application's responsibility to ensure that the callback function is thread-safe and that the delegate instance doesn't get collected by the Garbage Collector until <see cref="OpenCLContext"/> is disposed. If <paramref name="notify"/> is <c>null</c>, no callback function is registered. </param> /// <param name="userDataPtr"> Optional user data that will be passed to <paramref name="notify"/>. </param> public OpenCLContext(OpenCLDeviceType deviceType, OpenCLContextPropertyList properties, OpenCLContextNotifier notify, IntPtr userDataPtr) { IntPtr[] propertyArray = (properties != null) ? properties.ToIntPtrArray() : null; callback = notify; OpenCLErrorCode error = OpenCLErrorCode.Success; Handle = CL10.CreateContextFromType(propertyArray, deviceType, notify, userDataPtr, out error); OpenCLException.ThrowOnError(error); SetID(Handle.Value); this.properties = properties; OpenCLContextProperty platformProperty = properties.GetByName(OpenCLContextProperties.Platform); this.platform = OpenCLPlatform.GetByHandle(platformProperty.Value); this.devices = GetDevices(); //Trace.WriteLine("Create " + this + " in Thread(" + Thread.CurrentThread.ManagedThreadId + ").", "Information"); }
/// <summary> /// Creates a new <see cref="OpenCLContext"/> on a collection of <see cref="OpenCLDevice"/>s. /// </summary> /// <param name="devices"> A collection of <see cref="OpenCLDevice"/>s to associate with the <see cref="OpenCLContext"/>. </param> /// <param name="properties"> A <see cref="OpenCLContextPropertyList"/> of the <see cref="OpenCLContext"/>. </param> /// <param name="notify"> A delegate instance that refers to a notification routine. This routine is a callback function that will be used by the OpenCL implementation to report information on errors that occur in the <see cref="OpenCLContext"/>. The callback function may be called asynchronously by the OpenCL implementation. It is the application's responsibility to ensure that the callback function is thread-safe and that the delegate instance doesn't get collected by the Garbage Collector until <see cref="OpenCLContext"/> is disposed. If <paramref name="notify"/> is <c>null</c>, no callback function is registered. </param> /// <param name="notifyDataPtr"> Optional user data that will be passed to <paramref name="notify"/>. </param> public OpenCLContext(List <OpenCLDevice> devices, OpenCLContextPropertyList properties, OpenCLContextNotifier notify, IntPtr notifyDataPtr) { int handleCount; CLDeviceHandle[] deviceHandles = OpenCLTools.ExtractHandles(devices, out handleCount); IntPtr[] propertyArray = (properties != null) ? properties.ToIntPtrArray() : null; callback = notify; OpenCLErrorCode error = OpenCLErrorCode.Success; Handle = CL10.CreateContext(propertyArray, handleCount, deviceHandles, notify, notifyDataPtr, out error); OpenCLException.ThrowOnError(error); SetID(Handle.Value); this.properties = properties; OpenCLContextProperty platformProperty = properties.GetByName(OpenCLContextProperties.Platform); this.platform = OpenCLPlatform.GetByHandle(platformProperty.Value); this.devices = GetDevices(); //Trace.WriteLine("Create " + this + " in Thread(" + Thread.CurrentThread.ManagedThreadId + ").", "Information"); }
/// <summary> /// Creates a new <see cref="OpenCLContext"/> on a collection of <see cref="OpenCLDevice"/>s. /// </summary> /// <param name="devices"> A collection of <see cref="OpenCLDevice"/>s to associate with the <see cref="OpenCLContext"/>. </param> /// <param name="properties"> A <see cref="OpenCLContextPropertyList"/> of the <see cref="OpenCLContext"/>. </param> /// <param name="notify"> A delegate instance that refers to a notification routine. This routine is a callback function that will be used by the OpenCL implementation to report information on errors that occur in the <see cref="OpenCLContext"/>. The callback function may be called asynchronously by the OpenCL implementation. It is the application's responsibility to ensure that the callback function is thread-safe and that the delegate instance doesn't get collected by the Garbage Collector until <see cref="OpenCLContext"/> is disposed. If <paramref name="notify"/> is <c>null</c>, no callback function is registered. </param> /// <param name="notifyDataPtr"> Optional user data that will be passed to <paramref name="notify"/>. </param> public OpenCLContext(List<OpenCLDevice> devices, OpenCLContextPropertyList properties, OpenCLContextNotifier notify, IntPtr notifyDataPtr) { int handleCount; CLDeviceHandle[] deviceHandles = OpenCLTools.ExtractHandles(devices, out handleCount); IntPtr[] propertyArray = (properties != null) ? properties.ToIntPtrArray() : null; callback = notify; OpenCLErrorCode error = OpenCLErrorCode.Success; Handle = CL10.CreateContext(propertyArray, handleCount, deviceHandles, notify, notifyDataPtr, out error); OpenCLException.ThrowOnError(error); SetID(Handle.Value); this.properties = properties; OpenCLContextProperty platformProperty = properties.GetByName(OpenCLContextProperties.Platform); this.platform = OpenCLPlatform.GetByHandle(platformProperty.Value); this.devices = GetDevices(); //Trace.WriteLine("Create " + this + " in Thread(" + Thread.CurrentThread.ManagedThreadId + ").", "Information"); }
/// <summary> /// Creates a new <see cref="OpenCLContextPropertyList"/> which contains a single item specifying a <see cref="OpenCLPlatform"/>. /// </summary> /// <param name="platform"> A <see cref="OpenCLPlatform"/>. </param> public OpenCLContextPropertyList(OpenCLPlatform platform) { properties = new List <OpenCLContextProperty>(); properties.Add(new OpenCLContextProperty(OpenCLContextProperties.Platform, platform.Handle.Value)); }
private static void RunKernel(OpenCLPlatform platform, OpenCLDevice device) { var context = new OpenCLContext(new List<OpenCLDevice> {device}, new OpenCLContextPropertyList(platform), null, IntPtr.Zero); var program = LoadProgram(context, device, "ReductionUsingFSCLOpenCLManagedWrapper.reduction.cl"); var kernel1 = program.CreateKernel("reductionVector"); var kernel2 = program.CreateKernel("reductionComplete"); const int numValues = 1024 * 1024; const int numValuesPerWorkItem = 4; var globalWorkSize = numValues / numValuesPerWorkItem; const int localWorkSize = 32; var initialNumWorkGroups = globalWorkSize/localWorkSize; const int value = 42; var data = Enumerable.Repeat(value, numValues).Select(n => (float)n).ToArray(); var commandQueue = new OpenCLCommandQueue(context, device, OpenCLCommandQueueProperties.None); var floatType = typeof (float); var floatSize = sizeof (float); var dataBuffer1 = new OpenCLBuffer(context, OpenCLMemoryFlags.ReadWrite | OpenCLMemoryFlags.AllocateHostPointer, floatType, new long[] {numValues}); var dataBuffer2 = new OpenCLBuffer(context, OpenCLMemoryFlags.ReadWrite | OpenCLMemoryFlags.AllocateHostPointer, floatType, new long[] {initialNumWorkGroups*numValuesPerWorkItem}); var sumBuffer = new OpenCLBuffer(context, OpenCLMemoryFlags.WriteOnly | OpenCLMemoryFlags.AllocateHostPointer, floatType, new long[] { 1 }); var resultDataBuffer = dataBuffer2; using (var pinnedData = new PinnedObject(data)) { commandQueue.WriteToBuffer(pinnedData, dataBuffer1, true, 0L, numValues); } foreach (var index in Enumerable.Range(0, int.MaxValue)) { var dataBufferIn = index%2 == 0 ? dataBuffer1 : dataBuffer2; var dataBufferOut = index%2 == 0 ? dataBuffer2 : dataBuffer1; resultDataBuffer = dataBufferOut; kernel1.SetMemoryArgument(0, dataBufferIn); kernel1.SetMemoryArgument(1, dataBufferOut); kernel1.SetLocalArgument(2, localWorkSize*numValuesPerWorkItem*floatSize); Console.WriteLine($"Calling commandQueue.Execute(kernel1) with globalWorkSize: {globalWorkSize}; localWorkSize: {localWorkSize}; num work groups: {globalWorkSize / localWorkSize}"); commandQueue.Execute(kernel1, null, new long[] {globalWorkSize}, new long[] {localWorkSize}); globalWorkSize /= localWorkSize; if (globalWorkSize <= localWorkSize) break; } kernel2.SetMemoryArgument(0, resultDataBuffer); kernel2.SetLocalArgument(1, globalWorkSize*numValuesPerWorkItem*floatSize); kernel2.SetMemoryArgument(2, sumBuffer); Console.WriteLine($"Calling commandQueue.Execute(kernel2) with globalWorkSize: {globalWorkSize}; localWorkSize: {globalWorkSize}"); commandQueue.Execute(kernel2, null, new long[] { globalWorkSize }, new long[] { globalWorkSize }); commandQueue.Finish(); var sum = new float[1]; using (var pinnedSum = new PinnedObject(sum)) { commandQueue.ReadFromBuffer(sumBuffer, pinnedSum, true, 0L, 1L); } const int correctAnswer = numValues * value; Console.WriteLine($"OpenCL final answer: {Math.Truncate(sum[0]):N0}; Correct answer: {correctAnswer:N0}"); }