Multithreading in a MATLAB mex file

Together with colleagues from the F.C. Donders Centre and the NICI, I am currently working on a project on real-time analysis of EEG and MEG data for Brain-Computer Interfacing (BCI). Since we already have a lot of relevant code in MATLAB and since a lot of the target end-users are familiar with it, we would like to do the real-time processing in MATLAB.

The idea is to read the data that is streaming from the EEG amplifier, do the computation on the data (e.g. spatial filtering, spectral decomposition and classification) and then continue with the next section of the data. The challenge is not to lose any of the streaming EEG data while MATLAB is busy with the computation. A potential solution would be to implement the reading/acquisition of the data into matlab in a mex file which is multi-threaded.

For this purpose I wrote some code for testing the multithreading in MATLAB. The test code below demonstrates that it works, and shows how easy it actually is.

I am working on an Apple PowerBook G4 with OS X 10.4.11 and with MATLAB Version 7.4 (R2007a). The example code uses the POSIX Pthread libraries and I would expect the same code to work on most Unix and Linux systems. It will not work on a windows system, but might work with pthreads-win32.

Put the following code in a file with the name threads.c

#include < pthread.h > /* for threading */
#include < unistd.h > /* for sleep */
#include "mex.h"
#include "matrix.h"

void *do_thread(void *threadid)
{
int tid;
tid = (int)threadid;
mexPrintf("In thread: just started thread #%dn", tid);
sleep(4); /* pretend that the code is busy for a few seconds */
mexPrintf("In thread: about to exit from thread #%dn", tid);
pthread_exit(NULL);
}

void mexFunction (int nlhs, mxArray * plhs[], int nrhs, const mxArray * prhs[])
{
int num;

if (nrhs<1)
mexErrMsgTxt("not enough input arguments");
else
num = mxGetScalar(prhs[0]);

pthread_t threads[num];
int rc, t;
for(t=0; t < num ; t++){ mexPrintf("In main: creating thread %dn", t); rc = pthread_create(&threads[t], NULL, do_thread, (void *)t); if (rc){ mexErrMsgTxt("problem with return code from pthread_create()"); } sleep(1); /* wait some time before making the next thread */ } return; }

Subsequently, in MATLAB you should compile the mex file using the following command:

>> mex threads.c -lpthread

After that, you can run the mex function. It takes a single argument, corresponding to the number of threads to create. Each thread will live for three seconds (pretending that it is busy for some time), and the time between threads being created is one second. Some example output is below.

>> threads(6)
In main: creating thread 0
In thread: just started thread #0
In main: creating thread 1
In thread: just started thread #1
In main: creating thread 2
In thread: just started thread #2
In main: creating thread 3
In thread: just started thread #3
In thread: about to exit from thread #0
In main: creating thread 4
In thread: just started thread #4
In thread: about to exit from thread #1
In main: creating thread 5
In thread: just started thread #5
In thread: about to exit from thread #2
>> In thread: about to exit from thread #3
In thread: about to exit from thread #4
In thread: about to exit from thread #5
>>

You can see each thread starting and stopping. The last threads stop after the control has been returned to the MATLAB prompt.

Here you can find some comments from Mathworks, including some windows specific example code. Important to note is that MATLAB itself is single-threaded, and not thread safe. Hence you should take care in interfacing your threaded c-code in the mex file with the MATLAB core.

I would appreciate it to get some feedback on this. Please leave a comment below if you tested it successfully or if it does not work for you, with some details on your configuration (like operating system and MATLAB version).

12 thoughts on “Multithreading in a MATLAB mex file

  1. Shay

    Hey Robert,

    Would you mind performing a small variation in your test? When I was trying to figure this out, I found the mexPrintf was usually fine in threads, but that more elaborate mex calls eg mexEvalString(“eval(zeros(1,10));”); would cause matlab to crash.

    In your threads, instead of just sleeping for 4 seconds, would you try to say evaluate a matlab expression as well?

    Cheers,
    Shay

    Reply
  2. Robert

    Hi Shay,

    I have inserted mexEvalString(“eval(zeros(1,10));”); into the thread function as you suggested, and it indeed crashes. This is actually also what I would expect, since matlab is not thread-safe. The technical solution 1-V3B5T from Mathworks (see link in my post) states

    “… it is possible to create new threads from a C MEX-file in a supported fashion; as long as those threads do not access MATLAB in any way. Since the MEX API is not thread safe, no MEX API functions can be used in the spawned threads including printf because printf is defined to be mexPrintf in the mex.h header file…”

    See also http://en.wikipedia.org/wiki/Thread-safety

    Although my example runs through, it appears from the Mathworks comment that even mexPrintf and printf are forbidden. For me not being allowed to use mexXXX functions in the c-code is not a problem, because I don’t want the threads to access the matlab engine directly. In my application the thread should be listening to the external EEG data as it comes in, and I would rather use another (thread-safe) mex file to copy the data from buffer thread (c.f. shared memory between the threads in the different mex files) into matlab workspace.

    A work-around for the limitation in using mexXXX functions in the thread might be to use a mutex around each mexXXX call to ensure that they do not execute something simultaneously in the matlab engine. I tried that with

    pthread_mutex_lock(&mexMutex);
    mexEvalString(“eval(zeros(1,10));”);
    pthread_mutex_unlock(&mexMutex);

    But that does not seem to work, i.e. matlab again crashes.

    Robert

    Reply
  3. Shay

    Hey Robert,
    Thanks for doing that test. The results are as expected and consistent with my understanding as well. In fact I was surprised that your MexPrintf worked for you, when I tried that I managed to crash Matlab with that too.

    What I was trying to achieve was to create a MexFunction that would execute and return control back to Matlab, yet still have a thread running in the background that could communicated (2-ways) back to Matlab. The only way I have found to do this is with JAVA and associating callbacks to ActionListeners.

    Cheers,
    shay

    Reply
  4. Frank

    Thanks for the post. I am trying to implement the example you described on Matlab 2007b on OS X 10.5.4. I have the appropriate libraries and have added them to the path, but when I execute the mex threads.c -lpthread I get the following errors, any ideas what I am doing wrong?

    threads.c:1:43: error: pthread.h : No such file or directory
    threads.c:2:38: error: unistd.h : No such file or directory
    threads.c:3:10: error: #include expects “FILENAME” or
    threads.c:4:10: error: #include expects “FILENAME” or
    threads.c: In function ‘do_thread’:
    threads.c:10: error: syntax error before ‘?’ token
    threads.c:10: error: stray ‘#’ in program
    threads.c:10: error: stray ” in program
    threads.c:12: error: syntax error before ‘?’ token
    threads.c:12: error: stray ‘#’ in program
    threads.c:12: error: stray ” in program
    threads.c:13: error: ‘NULL’ undeclared (first use in this function)
    threads.c:13: error: (Each undeclared identifier is reported only once
    threads.c:13: error: for each function it appears in.)
    threads.c: At top level:
    threads.c:16: error: syntax error before ‘mxArray’
    threads.c: In function ‘mexFunction’:
    threads.c:20: error: ‘nrhs’ undeclared (first use in this function)
    threads.c:21: error: syntax error before ‘?’ token
    threads.c:25: error: ‘pthread_t’ undeclared (first use in this function)
    threads.c:29: error: ‘threads’ undeclared (first use in this function)
    threads.c:29: error: ‘NULL’ undeclared (first use in this function)

    mex: compile of ‘threads.c’ failed.

    Reply
  5. Robert

    the first two error lines indicate a general problem with the location of the include files (pthread.h and unistd.h). Normally the gcc compiler (which is called by the mex command) should find these include files automatically. You should check that gcc/SDK/Xcode are installed correctly on your system. If I do the following, I can see that the include files are present:

    manzana> locate pthread.h
    /Developer/SDKs/MacOSX10.4u.sdk/usr/include/pthread.h
    /Developer/SDKs/MacOSX10.5.sdk/usr/include/pthread.h

    manzana> locate unistd.h
    /Developer/SDKs/MacOSX10.4u.sdk/System/Library/Frameworks/Kernel.framework/Versions/A/Headers/libsa/unistd.h
    /Developer/SDKs/MacOSX10.4u.sdk/usr/include/sys/unistd.h
    /Developer/SDKs/MacOSX10.4u.sdk/usr/include/unistd.h
    /Developer/SDKs/MacOSX10.5.sdk/System/Library/Frameworks/Kernel.framework/Versions/A/Headers/libsa/unistd.h
    /Developer/SDKs/MacOSX10.5.sdk/usr/include/unistd.h

    have you ever tried compiling a “hello world”-like command line application? Or a simple command line threading example? If you cannot compile a simple command line application, then it is a problem with your gcc/SDK/Xcode installation. If it works on the command line and only fails in Matlab, then you can try “mex -setup” in matlab and try compiling another mex file.

    Reply
  6. Cesare

    To Frank,
    try removing the spaces before and after the symbols in and in the following include. It worked for me.

    To Robert,
    thanks for the nice example.

    Cesare

    Reply
  7. BELKACEM

    I need know at what time i run my matlab software ( or exactly I need this for each M-file)

    J’ai besoin de savoir à quelle heure je lance mon logiciel Matlab (ou exactement j’ai besoin de cela pour chaque M-file)

    Reply
    1. Robert

      For this you would not need a mex file or multithreading, but a plain function with a persistent variable. Something like this should do:

      function output = report_calltime(input)
      persistent storage

      if isempty(input)
      if isempty(storage)
      % create a new structure
      storage.parentname = evalin(‘caller’, ‘mfilename’); % get the mfilename of the calling function
      storage.time = clock; % get the current time
      else
      % append to the existing structure
      storage(end+1).parentname = evalin(‘caller’, ‘mfilename’); % get the mfilename of the calling function
      storage(end).time = clock; % get the current time
      end
      output = storage;
      clear storage
      end

      You would call “report_calltime” at the beginning of each of your functions. After they are done, you can do “storage = report_calltime(1)” to get the recorded structure.

      Note that I did not test the function that I just made up, so it might have some small errors.

      Reply
  8. Thomas

    Dear Robert,

    thank you very much for your post. What about using mxXXX functions like mxGetField? Those should be threadsafe, right?

    Greetings, Thomas

    Reply

Leave a Reply

Your email address will not be published. Required fields are marked *