I was migrating a function from a dll to C# and I found a line of code that I don't understand:
< Module >.lm_minimize(((Vector<CalPoint>)calPoints).Size, n_par1, par, (ILMCallbacks)callbacks, (lm_data_type)data, control);
When I try to enter the class there is code in hexadecimal (I guess it's auto generated code) that I can't copy.
This is the code:
internal static void lm_minimize(
int m_dat,
int n_par,
double[] par,
ILMCallbacks callbacks,
lm_data_type data,
lm_control_type control)
{
double[] numArray = new double[m_dat];
double[] diag = new double[n_par];
double[] qtf = new double[n_par];
double[] fjac = new double[m_dat * n_par];
double[] wa1 = new double[n_par];
double[] wa2 = new double[n_par];
double[] wa3 = new double[n_par];
double[] wa4 = new double[m_dat];
int[] ipvt = new int[n_par];
control.info = 0;
control.nfev = 0;
\u003CModule\u003E.lm_lmdif(m_dat, n_par, par, numArray, control.ftol, control.xtol, control.gtol, control.maxcall * (n_par + 1), control.epsilon, diag, 1, control.stepbound, ref control.info, ref control.nfev, fjac, ipvt, qtf, wa1, wa2, wa3, wa4, callbacks, data);
callbacks.lm_printout(n_par, par, m_dat, numArray, data, -1, 0, control.nfev);
control.fnorm = \u003CModule\u003E.\u003FA0x6d25334e\u002Elm_enorm(m_dat, 0, numArray);
if (control.info >= 0)
return;
control.info = 10;
}
And this code calls the function lm_mdif. Part of the code is like this:
\u003CModule\u003E.\u003FA0x6d25334e\u002E\u003F\u0024S1\u0040\u003F1\u003F\u003Flm_lmdif\u0040\u0040YMXHHP\u002401AN0NNNHN0HNA\u0024CAH10P\u002401AH00000A\u0024AAUILMCallbacks\u0040\u0040P\u0024AAVlm_data_type\u0040\u0040\u0040Z\u0040\u0024\u0024Q4IA |= 1U;
// ISSUE: fault handler
I wanted to know if anyone knows what the LM_MINIMIZE function is for, I can't find what it is for..
Thanks
I tried migrate the library code to C#.
Related
Can someone please guide me on how can I perform matrix multiplication in C# to use the GPU using opencl.
I have looked at opencl example here:
https://www.codeproject.com/Articles/1116907/How-to-Use-Your-GPU-in-NET
But I am not sure how to proceed for matrix multiplication.
yes as say doqtor, you need to flatten into 1D. So i have an example to use more args :
class Program
{
static string CalculateKernel
{
get
{
return #"
kernel void Calc(global int* m1, global int* m2, int size)
{
for(int i = 0; i < size; i++)
{
printf("" %d / %d\n"",m1[i],m2[i] );
}
}";
}
}
static void Main(string[] args)
{
int[] r1 = new int[]
{1, 2, 3, 4};
int[] r2 = new int[]
{4, 3, 2, 1};
int rowSize = r1.Length;
// 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 and
// create program with opencl source
ComputeProgram program = new ComputeProgram(context, CalculateKernel);
// compile opencl source
program.Build(null, null, null, IntPtr.Zero);
// load chosen kernel from program
ComputeKernel kernel = program.CreateKernel("Calc");
// allocate a memory buffer with the message (the int array)
ComputeBuffer<int> row1Buffer = new ComputeBuffer<int>(context,
ComputeMemoryFlags.ReadOnly | ComputeMemoryFlags.UseHostPointer, r1);
// allocate a memory buffer with the message (the int array)
ComputeBuffer<int> row2Buffer = new ComputeBuffer<int>(context,
ComputeMemoryFlags.ReadOnly | ComputeMemoryFlags.UseHostPointer, r2);
kernel.SetMemoryArgument(0, row1Buffer); // set the integer array
kernel.SetMemoryArgument(1, row2Buffer); // set the integer array
kernel.SetValueArgument(2, rowSize); // set the array size
// execute kernel
queue.ExecuteTask(kernel, null);
// wait for completion
queue.Finish();
Console.WriteLine("Finished");
Console.ReadKey();
}
another sample with the reading of result from gpubuffer:
class Program
{
static string CalculateKernel
{
get
{
// you could put your matrix algorithm here an take the result in array m3
return #"
kernel void Calc(global int* m1, global int* m2, int size, global int* m3)
{
for(int i = 0; i < size; i++)
{
int val = m2[i];
printf("" %d / %d\n"",m1[i],m2[i] );
m3[i] = val * 4;
}
}";
}
}
static void Main(string[] args)
{
int[] r1 = new int[]
{8, 2, 3, 4};
int[] r2 = new int[]
{4, 3, 2, 5};
int[] r3 = new int[4];
int rowSize = r1.Length;
// 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 and
// create program with opencl source
ComputeProgram program = new ComputeProgram(context, CalculateKernel);
// compile opencl source
program.Build(null, null, null, IntPtr.Zero);
// load chosen kernel from program
ComputeKernel kernel = program.CreateKernel("Calc");
// allocate a memory buffer with the message (the int array)
ComputeBuffer<int> row1Buffer = new ComputeBuffer<int>(context,
ComputeMemoryFlags.ReadOnly | ComputeMemoryFlags.UseHostPointer, r1);
// allocate a memory buffer with the message (the int array)
ComputeBuffer<int> row2Buffer = new ComputeBuffer<int>(context,
ComputeMemoryFlags.ReadOnly | ComputeMemoryFlags.UseHostPointer, r2);
// allocate a memory buffer with the message (the int array)
ComputeBuffer<int> resultBuffer = new ComputeBuffer<int>(context,
ComputeMemoryFlags.ReadOnly | ComputeMemoryFlags.UseHostPointer, new int[4]);
kernel.SetMemoryArgument(0, row1Buffer); // set the integer array
kernel.SetMemoryArgument(1, row2Buffer); // set the integer array
kernel.SetValueArgument(2, rowSize); // set the array size
kernel.SetMemoryArgument(3, resultBuffer); // set the integer array
// execute kernel
queue.ExecuteTask(kernel, null);
// wait for completion
queue.Finish();
GCHandle arrCHandle = GCHandle.Alloc(r3, GCHandleType.Pinned);
queue.Read<int>(resultBuffer, true, 0, r3.Length, arrCHandle.AddrOfPinnedObject(), null);
Console.WriteLine("display result from gpu buffer:");
for (int i = 0; i<r3.Length;i++)
Console.WriteLine(r3[i]);
arrCHandle.Free();
row1Buffer.Dispose();
row2Buffer.Dispose();
kernel.Dispose();
program.Dispose();
queue.Dispose();
context.Dispose();
Console.WriteLine("Finished");
Console.ReadKey();
}
}
you just adapt the kernel program to calculate the multiplication of 2 matrix
result of last program:
8 / 4
2 / 3
3 / 2
4 / 5
display result from gpu buffer:
16
12
8
20
Finished
to flatten 2d to 1d its really easy take this sample:
int[,] twoD = { { 1, 2,3 }, { 3, 4,5 } };
int[] oneD = twoD.Cast<int>().ToArray();
and see this link to do 1D -> 2D
I found a very good reference source for using OpenCL with dot Net.
This site is well structured and very useful. It also has matrix multiplication case study example.
OpenCL Tutorial
This is a follow on from this question.
I am trying to return an array of floating point numbers from C, to .Net. I will include some F# code, as well as C# code, so that people of either language can answer.
Unmanaged C code:
extern "C"
{
__declspec(dllexport) void DisplayHelloFromDLL(c_float* P_x, c_float* x)
{
//printf("Hello from DLL !\n");
//cout << "You gave me ... an int: " << i << endl;
// Load problem data
//c_float P_x[4] = { 4., 1., 1., 2., }; //covariance matrix
c_int P_nnz = 4; //number of non-zero elements in covar
c_int P_i[4] = { 0, 1, 0, 1, }; //row indices?
c_int P_p[3] = { 0, 2, 4}; //?
c_float q[2] = { 1., 1., }; //linear terms
c_float A_x[4] = { 1., 1., 1., 1., }; //constraint coefficients matrix
c_int A_nnz = 4; //number of non zero elements in constraints matrix
c_int A_i[4] = { 0, 1, 0, 2, }; //row indices?
c_int A_p[3] = { 0, 2, 4}; //?
c_float l[3] = { 1., 0., 0., }; //lower bounds
c_float u[3] = { 1., 0.7, 0.7, }; //upper bounds
c_int n = 2; //number of variables (x)
c_int m = 3; //number of constraints
// Problem settings
OSQPSettings *settings = (OSQPSettings *)c_malloc(sizeof(OSQPSettings));
// Structures
OSQPWorkspace *work; // Workspace
OSQPData *data; // OSQPData
// Populate data
data = (OSQPData *)c_malloc(sizeof(OSQPData));
data->n = n;
data->m = m;
data->P = csc_matrix(data->n, data->n, P_nnz, P_x, P_i, P_p);
data->q = q;
data->A = csc_matrix(data->m, data->n, A_nnz, A_x, A_i, A_p);
data->l = l;
data->u = u;
// Define Solver settings as default
osqp_set_default_settings(settings);
// Setup workspace
work = osqp_setup(data, settings);
// Solve Problem
osqp_solve(work);
//return the value
OSQPSolution* sol = work->solution;
x = sol->x;
// Clean workspace
osqp_cleanup(work);
c_free(data->A);
c_free(data->P);
c_free(data);
c_free(settings);
}
}
So all I have done is declared a parameter 'x', and I am setting it after the results are calculated.
F# code
open System.Runtime.InteropServices
module ExternalFunctions =
[<DllImport("TestLibCpp.dll")>]
extern void DisplayHelloFromDLL(float[] i, [<In>][<Out>] float[] x)
[<EntryPoint>]
let main argv =
let P_x = [|4.; 1.; 1.; 2.|]
let mutable xResult:float[] = [|0.;0.|]
ExternalFunctions.DisplayHelloFromDLL(P_x, xResult);
printfn "This is x:%A" xResult
0 // return an integer exit code
C# code
class Program
{
[DllImport("TestLibCpp.dll")]
public static extern void DisplayHelloFromDLL(double[] i, [In, Out] double[] x);
static void Main(string[] args)
{
Console.WriteLine("This is C# program");
double[] P_x = new double[] {4.0, 1.0, 1.0, 2.0};
double[] x = new double[] { 0.0, 0.0};
DisplayHelloFromDLL(P_x, x);
Console.WriteLine("Finished");
}
}
In both the F#, and C# cases, the value of x is unchanged.
I have tried other variations such as
open System.Runtime.InteropServices
module ExternalFunctions =
[<DllImport("TestLibCpp.dll")>]
extern void DisplayHelloFromDLL(float[] i, [<In>][<Out>] float[]& x)
[<EntryPoint>]
let main argv =
let P_x = [|4.; 1.; 1.; 2.|]
let mutable xResult:float[] = [|0.0; 0.0|]
ExternalFunctions.DisplayHelloFromDLL(P_x, &xResult);
printfn "This is x:%A" xResult
But I suspect the problem is the C code, not the .Net code. I think the problem is that work->solution->x is a pointer, not an array. I am guessing that I need to convert it from a pointer to an array, but can't work out how to do that. And again, not totally sure this is even the problem to begin with.
Thanks to PetSerAl for pointing (pun intended) me in the right direction.
All I needed to do was change part of the C code to
//return the value
OSQPSolution* sol = work->solution;
for (int i = 0; i != n; ++i)
x[i] = sol->x[i];
Just curious is there a quicker/neater way to achieve this:
double[] source = ... // some initialisation
var target = new double[1, source.Length];
for (var c = 0; c < source.Length; c++)
{
target[0, c] = source[c];
}
Initialiaze the array like this:
double[,] target = { { /* your list of values */ } };
Then you have a two dimentional array with only one row.
Since you are mentioning this is for P/Invoke, BlockCopy is probably reasonable to use:
double[] source = new double [] {1,2,3,4,7,8,9,0};// some initialisation
double[,] target = new double[1, source.Length];
Buffer.BlockCopy(source, 0, target, 0, source.Length * sizeof(double));
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.
Convertion from Double[] src to Byte[] dst
can be efficiently done in C# by fixed pointers:
fixed( Double* pSrc = src)
{
fixed( Byte* pDst = dst)
{
Byte* ps = (Byte*)pSrc;
for (int i=0; i < dstLength; i++)
{
*(pDst + i) = *(ps +i);
}
}
}
How can I do the same for List src ?
I.e. how can I get fixed pointer to array Double[]
included in List ?
Thanks.
I have used these helper methods before:
byte[] GetBytesBlock(double[] values)
{
var result = new byte[values.Length * sizeof(double)];
Buffer.BlockCopy(values, 0, result, 0, result.Length);
return result;
}
double[] GetDoublesBlock(byte[] bytes)
{
var result = new double[bytes.Length / sizeof(double)];
Buffer.BlockCopy(bytes, 0, result, 0, bytes.Length);
return result;
}
An example:
List<double> myList = new List<double>(){ 1.0, 2.0, 3.0};
//to byte[]
var byteResult = GetBytesBlock(myList.ToArray());
//back to List<double>
var doubleResult = GetDoublesBlock(byteResult).ToList();
not sure what you are intending, but I think ... you want
System.Runtime.Interopservices.Marshal.StructToPtr.
You can always use the ToArray() method on the List<Double> object to get a Double[].
You can use reflection to get the reference to the private T[] _items field, in the List instance.
Warning: In your code snippet, you need to make sure dstLength is the minimum of dst and src lengths in bytes, so that you don't try to copy more bytes than what are available. Probably you do so by creating dst with exactly the needed size to match the src, but your snippet doesn't make it clear.
Use the List<T>.ToArray() method and operate on the resulting array.
This might work, but you will have a data loss- content of the array will be 3 and 34 .
List<double> list = new List<double>();
list.Add(Math.PI);
list.Add(34.22);
byte[] arr = (from l in list
select (byte)l).ToArray<byte>();
Why don't you just access the list as usual?
List<double> list = new List<double>();
list.Add(Math.PI);
list.Add(34.22);
byte[] res = new byte[list.Count * sizeof(double)];
unsafe
{
fixed (byte* pres = res)
{
for (int i = 0; i < list.Count; i++)
{
*(((double*)pres) + i) = list[i];
}
}
}
I haven't tested it thoroughly and i seldomly need unsafe code, but it seems to work fine.
Edit: here is another (imo preferable) solution, without unsafe code:
int offset = 0;
for (int i = 0; i < list.Count; i++)
{
long num = BitConverter.DoubleToInt64Bits(list[i]);
for (int j = 0; j < 8; j++)
{
res[offset++] = (byte)num;
num >>= 8;
}
}