1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145
|
#if EXPERIMENTAL
using System;
using System.Collections.Generic;
using System.Text;
using OpenTK.Compute.CL10;
namespace Examples
{
using cl_context = IntPtr;
using cl_device_id = IntPtr;
using cl_command_queue = IntPtr;
using cl_program = IntPtr;
using cl_kernel = IntPtr;
using cl_mem = IntPtr;
[Example("Vector Addition", ExampleCategory.OpenCL, "1.0")]
class VectorAdd
{
public static void Main()
{
const int cnBlockSize = 4;
const int cnBlocks = 3;
IntPtr cnDimension = new IntPtr(cnBlocks * cnBlockSize);
string sProgramSource = @"
__kernel void
vectorAdd(__global const float * a,
__global const float * b,
__global float * c)
{
// Vector element index
int nIndex = get_global_id(0);
c[nIndex] = a[nIndex] + b[nIndex];
}
";
ErrorCode error;
// create OpenCL device & context
cl_context hContext;
unsafe { hContext = CL.CreateContextFromType((ContextProperties*)null, DeviceTypeFlags.DeviceTypeDefault, IntPtr.Zero, IntPtr.Zero, &error); }
// query all devices available to the context
IntPtr nContextDescriptorSize;
CL.GetContextInfo(hContext, ContextInfo.ContextDevices, IntPtr.Zero, IntPtr.Zero, out nContextDescriptorSize);
cl_device_id[] aDevices = new cl_device_id[nContextDescriptorSize.ToInt32()];
unsafe
{
fixed (cl_device_id* ptr = aDevices)
{
IntPtr ret;
CL.GetContextInfo(hContext, ContextInfo.ContextDevices, nContextDescriptorSize, new IntPtr(ptr), out ret);
}
}
// create a command queue for first device the context reported
cl_command_queue hCmdQueue = CL.CreateCommandQueue(hContext, aDevices[0], (CommandQueueFlags)0, out error);
// create & compile program
cl_program hProgram;
unsafe { hProgram = CL.CreateProgramWithSource(hContext, 1, new string[] { sProgramSource }, null, &error); }
CL.BuildProgram(hProgram, 0, (IntPtr[])null, null, IntPtr.Zero, IntPtr.Zero);
// create kernel
cl_kernel hKernel = CL.CreateKernel(hProgram, "vectorAdd", out error);
// allocate host vectors
float[] A = new float[cnDimension.ToInt32()];
float[] B = new float[cnDimension.ToInt32()];
float[] C = new float[cnDimension.ToInt32()];
// initialize host memory
Random rand = new Random();
for (int i = 0; i < A.Length; i++)
{
A[i] = rand.Next() % 256;
B[i] = rand.Next() % 256;
}
// allocate device memory
unsafe
{
fixed (float* pA = A)
fixed (float* pB = B)
fixed (float* pC = C)
{
cl_mem hDeviceMemA, hDeviceMemB, hDeviceMemC;
hDeviceMemA = CL.CreateBuffer(hContext,
MemFlags.MemReadOnly | MemFlags.MemCopyHostPtr,
new IntPtr(cnDimension.ToInt32() * sizeof(float)),
new IntPtr(pA),
out error);
hDeviceMemB = CL.CreateBuffer(hContext,
MemFlags.MemReadOnly | MemFlags.MemCopyHostPtr,
new IntPtr(cnDimension.ToInt32() * sizeof(float)),
new IntPtr(pA),
out error);
hDeviceMemC = CL.CreateBuffer(hContext,
MemFlags.MemWriteOnly,
new IntPtr(cnDimension.ToInt32() * sizeof(float)),
IntPtr.Zero,
out error);
// setup parameter values
CL.SetKernelArg(hKernel, 0, new IntPtr(sizeof(cl_mem)), new IntPtr(&hDeviceMemA));
CL.SetKernelArg(hKernel, 1, new IntPtr(sizeof(cl_mem)), new IntPtr(&hDeviceMemB));
CL.SetKernelArg(hKernel, 2, new IntPtr(sizeof(cl_mem)), new IntPtr(&hDeviceMemC));
// write data from host to device
CL.EnqueueWriteBuffer(hCmdQueue, hDeviceMemA, true, IntPtr.Zero,
new IntPtr(cnDimension.ToInt32() * sizeof(float)),
new IntPtr(pA), 0, null, (IntPtr[])null);
CL.EnqueueWriteBuffer(hCmdQueue, hDeviceMemB, true, IntPtr.Zero,
new IntPtr(cnDimension.ToInt32() * sizeof(float)),
new IntPtr(pB), 0, null, (IntPtr[])null);
// execute kernel
error = (ErrorCode)CL.EnqueueNDRangeKernel(hCmdQueue, hKernel, 1, null, &cnDimension, null, 0, null, null);
if (error != ErrorCode.Success)
throw new Exception(error.ToString());
// copy results from device back to host
IntPtr event_handle = IntPtr.Zero;
error = (ErrorCode)CL.EnqueueReadBuffer(hCmdQueue, hDeviceMemC, true, IntPtr.Zero,
new IntPtr(cnDimension.ToInt32() * sizeof(float)),
new IntPtr(pC), 0, null, (IntPtr[])null);
if (error != ErrorCode.Success)
throw new Exception(error.ToString());
CL.Finish(hCmdQueue);
CL.ReleaseMemObject(hDeviceMemA);
CL.ReleaseMemObject(hDeviceMemB);
CL.ReleaseMemObject(hDeviceMemC);
}
}
for (int i = 0; i < A.Length; i++)
{
System.Diagnostics.Trace.WriteLine(String.Format("{0} + {1} = {2}", A[i], B[i], C[i]));
}
}
}
}
#endif
|