27Jul/10Off

Using CULA in MATLAB, Part 3

by Kyle

In part one of this three part series, we introduced a method using C++ templates to support all four major MATLAB data types. In part two, we detailed the specifics of how to integrate CULA's SVD algorithm into MATLAB. Finally, in todays section we'll give some tips on error checking, compilation, linking, usage, and benchmarking.

The code posted in the previous two examples didn't include any error checking. For example, if an allocation on the device failed because your GPU doesn't have enough memory, the error will be silently ignored and MATLAB will most likely return blank answers. Similarly, if no CUDA enable GPU is found, the original code will continue with no visible problem. These potential errors can all be handled by the culaStatus variable and the MATLAB error handler, mexErrMsgIdAndTxt(). By using these two tools, we can detect a CULA error and safely return control to MATLAB with a visible error. Another option, which I won't outline here would be fall back original MATLAB built in function.

The following addition to the header provides are nice parser of culaStatus errors. If no error is found, the code returns immediately. Otherwise, we describe the error to MATLAB.

#ifndef __CULAMEX_HPP__
#define __CULAMEX_HPP__

// Header code from Part 2

void checkStatus(culaStatus status, const char* funcname)
{
    if(!status)
        return;

    culaShutdown();

    char id[128];
    sprintf(id, "CULA:%s:", funcname);

    if(status == culaArgumentError)
    {
        strcat(id, "culaArgumentError");
        mexErrMsgIdAndTxt(id, "%s: Invalid value for parameter %d\n", funcname, culaGetErrorInfo());
    }
    else if(status == culaDataError)
    {
        strcat(id, "culaDataError");
        mexErrMsgIdAndTxt(id, "%s: Data error (%d)\n", funcname, culaGetErrorInfo());
    }
    else if(status == culaBlasError)
    {
        strcat(id, "culaBlasError");
        mexErrMsgIdAndTxt(id, "%s: Blas error (%d)\n", funcname, culaGetErrorInfo());
    }
    else if(status == culaRuntimeError)
    {
        strcat(id, "culaRuntimeError");
        mexErrMsgIdAndTxt(id, "%s: Runtime error (%d)\n", funcname, culaGetErrorInfo());
    }
    else if(status == culaNotInitialized)
        strcat(id, "culaNotInitialized");
    else if(status == culaNoHardware)
        strcat(id, "culaNoHardware");
    else if(status == culaInsufficientRuntime)
        strcat(id, "culaInsufficientRuntime");
    else if(status == culaInsufficientComputeCapability)
        strcat(id, "culaInsufficientComputeCapability");
    else if(status == culaInsufficientMemory)
        strcat(id, "culaInsufficientMemory");
    else if(status == culaFeatureNotImplemented)
        strcat(id, "culaFeatureNotImplemented");
    else
        strcat(id, "unknown");

    // Message that don't have error info fall through to here
    mexErrMsgIdAndTxt(id, "%s: %s\n", funcname, culaGetStatusString(status));
}

#endif // __CULAMEX_HPP__

In the main code, simply call the checkStatus() function after any GPU call that can fail.

// Initialize CULA
culaStatus status = culaInitialize();
checkStatus(status, "culaInitialize");

// SVD Factorization
status = culaGesvd('A', 'A', M, N, A, M, SVEC, U, M, VT, N);
checkStatus(status, "culaGesvd");

Now we'll move onto some basic MATLAB compilation.  At the MATLAB command line simply type,

mex -setup

and you'll see a list of compilers available on your machine. Select your compiler of choice and continue. Please note that the default compiler included with MATLAB on Windows, lcc, does not support all of the C++ functionality needed to compile the file examples we have provided. However, Visual Studio Express 2008 and 2010 are free of charge and will get the job done.

Next, to call your newly configured compiler type,

mex( ['-I' getenv('CULA_INC_PATH')], ['-L' getenv('CULA_LIB_PATH_64')], '-lcula', 'culasvd.cpp' )

where the CULA_INC_PATH and CULA_LIB_PATH_64 environment variables are set to the location of the CULA headers and libraries. These are typically set by the CULA installer. If everything goes successfully, you've now generated a file named culasvd.mexa64, where the suffix is dependent on your system. The function will now be usable by simply calling:

[u,s,v] = culasvd(A)

If you see an error: "The specified module could not be found," a shared CULA library could not be loaded by MATLAB. The solution to this varies from platform to platform, but a surefire fix is to simply copy all of the shared libraries in your CULA bin/bin64 folder into the folder containing your newly created mex functions.

Try benchmarking your code and see what kind of results you get! We've seen upwards of 5-10x speed ups for a number of CULA functions.

N = 2048;
A = rand(N);
tic; [u,s,v] = culasvd(A); toc;
Elapsed time is 14.432616 seconds.
tic; [u,s,v] = svd(A); toc;
Elapsed time is 103.646813 seconds.

I hope this example proved useful to you. At sometime in the near future, we'll be posting information on how to use a number of other functions within MATLAB. Again, if you have any questions or comments, please visit our forums!

More Information:
CULA Programmers Guide: http://www.culatools.com/html_guide/
MATLAB MEX-file Guide: http://www.mathworks.com/support/tech-notes/1600/1605.html
C++ Templates: http://en.wikipedia.org/wiki/Template_(programming)

Comments (0) Trackbacks (0)

Sorry, the comment form is closed at this time.

Trackbacks are disabled.