I am trying to get a simple Cloo program to run but it is not working, can anyone tell me why?
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Cloo;
using System.Runtime.InteropServices;
namespace HelloWorld
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
ComputeContextPropertyList cpl = new ComputeContextPropertyList(ComputePlatform.Platforms[0]);
ComputeContext context = new ComputeContext(ComputeDeviceTypes.Gpu, cpl, null, IntPtr.Zero);
string kernelSource = #"
kernel void VectorAdd(
global read_only float* a,
global read_only float* b,
global write_only float* c )
{
int index = get_global_id(0);
c[index] = a[index] + b[index];
}
";
long count = 20;
float[] arrA = new float[count];
float[] arrB = new float[count];
float[] arrC = new float[count];
Random rand = new Random();
for (int i = 0; i < count; i++)
{
arrA[i] = (float)(rand.NextDouble() * 100);
arrB[i] = (float)(rand.NextDouble() * 100);
}
ComputeBuffer<float> a = new ComputeBuffer<float>(context, ComputeMemoryFlags.ReadOnly | ComputeMemoryFlags.CopyHostPointer, arrA);
ComputeBuffer<float> b = new ComputeBuffer<float>(context, ComputeMemoryFlags.ReadOnly | ComputeMemoryFlags.CopyHostPointer, arrB);
ComputeBuffer<float> c = new ComputeBuffer<float>(context, ComputeMemoryFlags.WriteOnly, arrC.Length);
ComputeProgram program = new ComputeProgram(context, new string[] { kernelSource });
program.Build(null, null, null, IntPtr.Zero);
ComputeKernel kernel = program.CreateKernel("VectorAdd");
kernel.SetMemoryArgument(0, a);
kernel.SetMemoryArgument(1, b);
kernel.SetMemoryArgument(2, c);
ComputeCommandQueue commands = new ComputeCommandQueue(context, context.Devices[0], ComputeCommandQueueFlags.None);
ComputeEventList events = new ComputeEventList();
commands.Execute(kernel, null, new long[] { count }, null, events);
arrC = new float[count];
GCHandle arrCHandle = GCHandle.Alloc(arrC, GCHandleType.Pinned);
commands.Read(c, false, 0, count, arrCHandle.AddrOfPinnedObject(), events);
commands.Finish();
arrCHandle.Free();
for (int i = 0; i < count; i++)
richTextBox1.Text += "{" + arrA[i] + "} + {" + arrB[i] + "} = {" + arrC[i] + "} \n";
}
}
}
This is the error the program gives me
an unhandled exception of type
'Cloo.InvalidBinaryComputeException'
occurred in Cloo.dll
Additional information: OpenCL error
code detected: InvalidBinary.
This looks identical to the VectorAddTest that is distributed with Cloo.
Are you using ATI Stream? If yes, this may be a problem related to this: http://sourceforge.net/tracker/?func=detail&aid=2946105&group_id=290412&atid=1229014
Clootils works around this problem by allocating a console. Check Clootils/Program.cs for implementation details.
Change the kernel name - I think the name VectorAdd conflicts with something.
Related
I am busy rewriting a piece of code from C++ in to C#
Currently I am stuck at the following
pCommBuf = new BYTE[nSize+SB_OEM_HEADER_SIZE+SB_OEM_DEV_ID_SIZE+SB_OEM_CHK_SUM_SIZE];
nReceivedBytes = comm_recv( pCommBuf, nSize+SB_OEM_HEADER_SIZE+SB_OEM_DEV_ID_SIZE+SB_OEM_CHK_SUM_SIZE, gCommTimeOut );
if( nReceivedBytes != nSize+SB_OEM_HEADER_SIZE+SB_OEM_DEV_ID_SIZE+SB_OEM_CHK_SUM_SIZE )
{
if(pCommBuf)
delete pCommBuf;
return PKT_COMM_ERR;
}
memcpy(Buf, pCommBuf, SB_OEM_HEADER_SIZE+SB_OEM_DEV_ID_SIZE);
memcpy(pBuf, pCommBuf+SB_OEM_HEADER_SIZE+SB_OEM_DEV_ID_SIZE, nSize);
wReceivedChkSum = *(WORD*)(pCommBuf+nSize+SB_OEM_HEADER_SIZE+SB_OEM_DEV_ID_SIZE);
I have the code working up to this point
//memcpy(Buf, pCommBuf, SB_OEM_HEADER_SIZE+SB_OEM_DEV_ID_SIZE);
Marshal.Copy(pCommBuf, Buf, 0, (int)(SB_OEM_HEADER_SIZE + SB_OEM_DEV_ID_SIZE)); // This works
//memcpy(pBuf, pCommBuf+SB_OEM_HEADER_SIZE+SB_OEM_DEV_ID_SIZE, nSize);
I am not sure how to do pCommBuf+SB_OEM_HEADER_SIZE+SB_OEM_DEV_ID_SIZE in C#, pCommBuff is a IntPtr and in C++ Byte*
You simply need to change the start offset for the 2nd copy :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
namespace ConsoleApplication1
{
class Program
{
const int SB_OEM_HEADER_SIZE = 10;
const int SB_OEM_DEV_ID_SIZE = 10;
const int SB_OEM_CHK_SUM_SIZE = 10;
static void Main(string[] args)
{
int nSize = 1024;
byte[] nBuf = new byte[nSize];
byte[] Buf = new byte[SB_OEM_HEADER_SIZE + SB_OEM_DEV_ID_SIZE];
IntPtr pCommBuf = Marshal.AllocHGlobal(nSize + SB_OEM_HEADER_SIZE + SB_OEM_DEV_ID_SIZE + SB_OEM_CHK_SUM_SIZE);
Marshal.Copy(nBuf, 0, pCommBuf, nSize);
Marshal.Copy(pCommBuf + nSize , Buf, 0, (int)(SB_OEM_HEADER_SIZE + SB_OEM_DEV_ID_SIZE));
}
}
}
L want to learn the C# opencl.net to accelerate the code by gpu, this code is in the website https://habrahabr.ru/post/124873/, l cannot understand the meaning, anyone can explain it, and anywhere can l learn about the opencl.net, thank u very much.
private void button4_Click(object sender, EventArgs e)
{
//Установка параметров, инициализирующих видеокарты при работе. В Platforms[1] должен стоять индекс
//указывающий на используемую платформу
ComputeContextPropertyList Properties = new ComputeContextPropertyList(ComputePlatform.Platforms[1]);
ComputeContext Context = new ComputeContext(ComputeDeviceTypes.All, Properties, null, IntPtr.Zero);
//Текст програмы, исполняющейся на устройстве (GPU или CPU). Именно эта программа будет выполнять паралельные
//вычисления и будет складывать вектора. Программа написанна на языке, основанном на C99 специально под OpenCL.
string vecSum = #"
__kernel void
floatVectorSum(__global float * v1,
__global float * v2)
{
int i = get_global_id(0);
v1[i] = v1[i] + v2[i];
}
";
//Список устройств, для которых мы будем компилировать написанную в vecSum программу
List<ComputeDevice> Devs = new List<ComputeDevice>();
Devs.Add(ComputePlatform.Platforms[1].Devices[0]);
Devs.Add(ComputePlatform.Platforms[1].Devices[1]);
Devs.Add(ComputePlatform.Platforms[1].Devices[2]);
//Компиляция программы из vecSum
ComputeProgram prog = null;
try
{
prog = new ComputeProgram(Context, vecSum); prog.Build(Devs, "", null, IntPtr.Zero);
}
catch
{ }
//Инициализация новой программы
ComputeKernel kernelVecSum = prog.CreateKernel("floatVectorSum");
//Инициализация и присвоение векторов, которые мы будем складывать.
float[] v1 = new float[100], v2 = new float[100];
for (int i = 0; i < v1.Length; i++)
{
v1[i] = i;
v2[i] = 2 * i;
}
//Загрузка данных в указатели для дальнейшего использования.
ComputeBuffer<float> bufV1 = new ComputeBuffer<float>(Context, ComputeMemoryFlags.ReadWrite | ComputeMemoryFlags.UseHostPointer, v1);
ComputeBuffer<float> bufV2 = new ComputeBuffer<float>(Context, ComputeMemoryFlags.ReadWrite | ComputeMemoryFlags.UseHostPointer, v2);
//Объявляем какие данные будут использоваться в программе vecSum
kernelVecSum.SetMemoryArgument(0, bufV1);
kernelVecSum.SetMemoryArgument(1, bufV2);
//Создание програмной очереди. Не забудте указать устройство, на котором будет исполняться программа!
ComputeCommandQueue Queue = new ComputeCommandQueue(Context, Cloo.ComputePlatform.Platforms[1].Devices[0], Cloo.ComputeCommandQueueFlags.None);
//Старт. Execute запускает программу-ядро vecSum указанное колличество раз (v1.Length)
Queue.Execute(kernelVecSum, null, new long[] { v1.Length }, null, null);
//Считывание данных из памяти устройства.
float[] arrC = new float[100];
GCHandle arrCHandle = GCHandle.Alloc(arrC, GCHandleType.Pinned);
Queue.Read<float>(bufV1, true, 0, 100, arrCHandle.AddrOfPinnedObject(), null);
}
private void button4_Click(object sender, EventArgs e)
{
ComputeContextPropertyList Properties = new ComputeContextPropertyList(ComputePlatform.Platforms[1]);
ComputeContext Context = new ComputeContext(ComputeDeviceTypes.All, Properties, null, IntPtr.Zero);
//define a function template that sum two vectors
string vecSum = #"
__kernel void
floatVectorSum(__global float * v1,
__global float * v2)
{
int i = get_global_id(0);
v1[i] = v1[i] + v2[i];
}
";
//add gpu devices into list for executing the vecSum function defined at last step
List<ComputeDevice> Devs = new List<ComputeDevice>();
Devs.Add(ComputePlatform.Platforms[1].Devices[0]);
Devs.Add(ComputePlatform.Platforms[1].Devices[1]);
Devs.Add(ComputePlatform.Platforms[1].Devices[2]);
//define a compute programe with function define and gpu devices specified.
ComputeProgram prog = null;
try
{
prog = new ComputeProgram(Context, vecSum); prog.Build(Devs, "", null, IntPtr.Zero);
}
catch
{ }
ComputeKernel kernelVecSum = prog.CreateKernel("floatVectorSum");
//init the vectors need by the vecSum.
float[] v1 = new float[100], v2 = new float[100];
for (int i = 0; i < v1.Length; i++)
{
v1[i] = i;
v2[i] = 2 * i;
}
//create parametes needed as pass in parameter for vecSum.
ComputeBuffer<float> bufV1 = new ComputeBuffer<float>(Context, ComputeMemoryFlags.ReadWrite | ComputeMemoryFlags.UseHostPointer, v1);
ComputeBuffer<float> bufV2 = new ComputeBuffer<float>(Context, ComputeMemoryFlags.ReadWrite | ComputeMemoryFlags.UseHostPointer, v2);
//pass the parameters in.
kernelVecSum.SetMemoryArgument(0, bufV1);
kernelVecSum.SetMemoryArgument(1, bufV2);
//queue your compute request.
ComputeCommandQueue Queue = new ComputeCommandQueue(Context, Cloo.ComputePlatform.Platforms[1].Devices[0], Cloo.ComputeCommandQueueFlags.None);
//execute your compute request
Queue.Execute(kernelVecSum, null, new long[] { v1.Length }, null, null);
//clean the resource and read the result from the queue
float[] arrC = new float[100];
GCHandle arrCHandle = GCHandle.Alloc(arrC, GCHandleType.Pinned);
Queue.Read<float>(bufV1, true, 0, 100, arrCHandle.AddrOfPinnedObject(), null);
}
I've readed a few articles on stackoverflow but i couldn't figure out how to do it. I've made a small code for reading mixed\binary files (making a new one, with separated methods, the older one was messed) - but i'm in doubt on how to call the method on the program's main.
I figured out i should instantiate each variable before using them on the method's call - but how do i do that with string ? I know this is a newbie question but i'm new to c# - also i've searched over stackoverflow and other places and couldn't find an suitable answer.
Thanks.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using System.Windows.Forms;
namespace ConsoleApplication2
{
class Program
{
public void FileOpen(ref OpenFileDialog of, ref string filename, ref int nfiles)
{
of.Filter = "PPF Files | *.ppf";
of.Multiselect = true;
of.ShowDialog();
filename = of.FileName;
nfiles = of.FileNames.Count();
}
public void FileRead(ref OpenFileDialog of, ref string filename, ref List<string> freaded, ref int nfiles, ref string filecontents)
{
string aux;
List<string> filesreaded = new List<string>();
if (string.IsNullOrEmpty(of.FileName) == false)
{
for(int i=0; i<nfiles; i++)
{
// Read the file into <bits>
using (var fs = new FileStream(filename, FileMode.Open, FileAccess.ReadWrite, FileShare.None))
{
var len = (int)fs.Length;
var bits = new byte[len];
fs.Read(bits, 0, len);
// Dump 16 bytes per line
for (int ix = 0; ix < len; ix += 16)
{
var cnt = Math.Min(16, len - ix);
var line = new byte[cnt];
Array.Copy(bits, ix, line, 0, cnt);
// Convert non - ascii characters to .
for (int jx = 0; jx < cnt; ++jx)
{
if (line[jx] < 0x20 || line[jx] > 0x7f)
line[jx] = (byte)'.';
}
aux = Encoding.ASCII.GetString(line);
filecontents += aux;
}
}//Closing FileStream
}//Closing files loop (operations for each file)
}//Closing IF Statement
}//Closing FileRead function
[STAThread]
static void Main(string[] args)
{
Program a = new Program();
OpenFileDialog openf = new OpenFileDialog();
int filenumber = new int();
string fullfilename //What to do here?
//How can i instantiate a new string so i can use it when calling the method ?
a.FileOpen(ref openf , ref fullfilename , ref filenumber);
}
}
}
I'm trying to get this demo to build but I get this error
I've tried this with mono and visual studio 2010, same problem
The error occurs on line
program.Build(null, null, null, IntPtr.Zero);
EDIT
C#
using System;
using Cloo;
using System.Collections.Concurrent;
using System.Threading.Tasks;
using System.IO;
namespace ClooTest
{
class MainClass
{
public static void Main (string[] args)
{
// pick first platform
ComputePlatform platform = ComputePlatform.Platforms[0];
// create context with all gpu devices
ComputeContext context = new ComputeContext(ComputeDeviceTypes.Gpu,
new ComputeContextPropertyList(platform), null, IntPtr.Zero);
// create a command queue with first gpu found
ComputeCommandQueue queue = new ComputeCommandQueue
(
context,
context.Devices[0],
ComputeCommandQueueFlags.None
);
// load opencl source
StreamReader streamReader = new StreamReader("kernels.cl");
string clSource = streamReader.ReadToEnd();
streamReader.Close();
// create program with opencl source
ComputeProgram program = new ComputeProgram(context, clSource);
// compile opencl source
program.Build(null, null, null, IntPtr.Zero);
// load chosen kernel from program
ComputeKernel kernel = program.CreateKernel("helloWorld");
// create a ten integer array and its length
int[] message = new int[] { 1, 2, 3, 4, 5 };
int messageSize = message.Length;
// allocate a memory buffer with the message (the int array)
ComputeBuffer<int> messageBuffer = new ComputeBuffer<int>(context,
ComputeMemoryFlags.ReadOnly | ComputeMemoryFlags.UseHostPointer, message);
kernel.SetMemoryArgument(0, messageBuffer); // set the integer array
kernel.SetValueArgument(1, messageSize); // set the array size
// execute kernel
queue.ExecuteTask(kernel, null);
// wait for completion
queue.Finish();
}
}
}
OpenCL
kernel void helloWorld(global read_only int* message, int messageSize) {
for (int i = 0; i < messageSize; i++) {
printf("%d", message[i]);
}
}
EDIT
Yeah print probably isn't very well supported. I would suggest performing your "Hello world" with some simple number crunching instead. Maybe something like:
kernel void IncrementNumber(global float4 *celldata_in, global float4 *celldata_out) {
int index = get_global_id(0);
float4 a = celldata_in[index];
a.w = a.w + 1;
celldata_out[index] = a;
}
I got stuck with Access violation exception in managed code. Histogram pointer is not null and everything seems ok. Got example of creating IntPtr's from http://www.emgu.com/forum/viewtopic.php?f=8&t=59
// initializing data
var random = new Random();
var array = new double[1000];
for (int i = 0; i < 1000; i++)
{
array[i] = random.NextDouble();
}
var arrayPtr = GetDataPtr(array);
//initializing ranges array
double[] rangesArray = { 0, 1 };
var rangesArrayPtr = GetRangesArrayPtr(rangesArray);
//creating and querying histogram
var histogramStructure = CvInvoke.cvCreateHist(1, new[] {20}, HIST_TYPE.CV_HIST_ARRAY, rangesArrayPtr, true);
var histogram = CvInvoke.cvMakeHistHeaderForArray(1, new[] { 20 }, histogramStructure, arrayPtr, rangesArrayPtr, 1);
CvInvoke.cvNormalizeHist(histogram, 1.0);
CvInvoke.cvQueryHistValue_1D(histogram, 0); // getting exception here
help methods
private static IntPtr[] GetRangesArrayPtr(double[] array)
{
var ranges = new IntPtr[1];
ranges[0] = Marshal.AllocHGlobal(array.Length * sizeof(double));
Marshal.Copy(array, 0, ranges[0], array.Length);
return ranges;
}
private static IntPtr GetDataPtr(double[] array)
{
var ranges = new IntPtr();
ranges = Marshal.AllocHGlobal(array.Length * sizeof(double));
Marshal.Copy(array, 0, ranges,array.Length);
return ranges;
}
I had the same problem in a recent project and solved it by copying the histogram values into a new array.
Double[] histtemp = new double[255];
Histogram.MatND.ManagedArray.CopyTo(histtemp,0);
Now you can access the histogram values in histtemp. I hope it will help future viewers.