Monday, 18 June 2012

Using NAG and LabVIEW in a 64 bit environment

This is the latest in a series of blog posts about enhancing LabVIEW applications by using NAG methods and routines; previously, we've described in detail how to invoke methods from the NAG Library for .NET in LabVIEW, and how to call routines from the NAG Fortran and C libraries from within that programming environment.  In addition, we supplemented those descriptions with an archive of examples which is available from the NAG LabVIEW page.

The examples we looked at previously were all in the 32 bit environment, but some users have asked whether all this works in the 64 bit world, being keen to take advantage of the larger address space of that architecture.  Indeed it does, as we shall show here.

Tuesday, 12 June 2012

So just how expensive is Marshaling?

One complication in using the NAG C Library from .NET is callback functions which, in C, have arrays in their parameter lists. Take for example the optimization algorithm e04nfc(nag_opt_qp) for quadratic programming problems. This NAG function requires a callback function qphess of the following C prototype:
void qphess(Integer n, Integer jthcol, const double h[], Integer tdh,
            const double x[], double hx[], Nag_Comm *comm);

In C# the corresponding delegate is

public delegate void  NAG_E04NFC_QPHESS (int n, int jthcol,
    IntPtr h_ptr, int tdh, IntPtr x_ptr, [In, Out] IntPtr hx,
    ref CommStruct comm);

If you follow the C example program for nag_opt_qp as well as the style of the NAG C# examples you will write something like this for qphess in C#:

static void qphess0(int n, int jthcol, IntPtr h_ptr, int tdh,
                    IntPtr x_ptr, [In, Out] IntPtr hx_ptr,
                    ref CommStruct comm)
            double[] xloc = new double[n];
            double[] hloc = new double[n * n];
            double[] hxloc = new double[n];

            Marshal.Copy(h_ptr, hloc, 0, n * n);
            Marshal.Copy(x_ptr, xloc, 0, n);

            for (int i = 0; i < n; ++i) hxloc[i] = 0;
            for (int i = 0; i < n; ++i)
                for (int j = 0; j < n; ++j)
                    hxloc[i] += hloc[i * n + j] * xloc[j];

            Marshal.Copy(hxloc, 0, hx_ptr, n);

Marshaling can be fairly expensive, and in some cases it may be best to avoid it. The cost is trivial for the small example programs NAG provides, but it quickly mounts with increasing problem size. For n of 1000 and this version of qphess, nag_opt_qp takes about 7 seconds to solve a typical problem on my laptop.