Matlab Mex library lifecycle

雨燕双飞 提交于 2019-12-29 04:45:11

问题


Does anyone know what the matlab mex library lifecycle is? Specifically I am interested in the following:

  1. Is there a way to force the library to be loaded before invoking it?
  2. Is the library a singleton or are multiple instances loaded?
  3. Are there any hooks for initialization prior to invocation?
  4. Is there a destructor hook/signal that can be intercepted when the library is unloaded for cleanup?

I did an extensive search here and online and I could not find the answers to these questions. My problem has some performance cost with initialization and I would like to avoid that if possible, without needing to write a service.


回答1:


As I mentioned in the comments, in Windows you could implement DllMain entry point. This is because MEX-file are just regular DLL files with different extension. Here is a minimal example:

testDLL.cpp

#include "mex.h"
#include <windows.h>

BOOL APIENTRY DllMain(HANDLE hModule, DWORD dwReason, LPVOID lpReserved)
{
    switch (dwReason) {
    case DLL_PROCESS_ATTACH:
        mexPrintf("DLL_PROCESS_ATTACH: hModule=0x%x\n", hModule);
        break;
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
        break;
    case DLL_PROCESS_DETACH:
        mexPrintf("DLL_PROCESS_DETACH: hModule=0x%x\n", hModule);
        break;
    }
    return TRUE;
}

void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
    mexPrintf("Inside MEX-function\n");
}

Here is how it works:

>> mex -largeArrayDims testDLL.cpp

>> testDLL
DLL_PROCESS_ATTACH: hModule=0xa0980000
Inside MEX-function

>> testDLL
Inside MEX-function

>> clear testDLL
DLL_PROCESS_DETACH: hModule=0xa0980000



回答2:


A MEX file stays loaded until you clear it (clear myMexFun or clear mex) or quit MATLAB.

For pre-loading, all I can suggest is to call the function with no inputs or with nop-equivalent inputs. I have created simple code paths in my mexFunctions to handle such calls without error, the simplest example being if(!nrhs) return;. Subsequent calls will not need to load the mexFunction from disk (or any other functions in shared libraries called by the MEX function) and you do not need to worry about initialization cost after that.

Regarding initialization/cleanup, constructors/destructors, etc. I am not aware of any way to see what MATLAB is doing when loading or unloading the MEX file, but a MEX file is a regular shared library (i.e. DLL/SO) that just exports a single function (mexFunction is the only entry point), so, as Amro points out, you can implement a DllMain in Windows to define module and thread attach/detach operations (see the excellent example in his answer). I'm not aware of any other mechanisms for interacting with the library.

To perform tasks when the module unloads, you can use mexAtExit within mexFunction to register with MATLAB a function to call when the MEX function unloads (again, cleared or MATLAB exits). Simply define a static function in the global namespace and register it with mexAtExit. The example provided by MATLAB (mexatexit.c) demonstrates closing a file stream that was opened within mexFunction, but not closed. You could also free persistent memory, close streams, etc. Here is a contrived example:

mexDLLtext.cpp:

#include "mex.h"
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>

static FILE   *fp=NULL;
static double *pDataC=NULL, *pDataCpp=NULL, *pMxData=NULL;
static char fName[L_tmpnam], counter = 0;

static void CleanUp(void)
{
  fclose(fp);        /* close file opened with fopen */
  free(pDataC);      /* deallocate buffer allocated with malloc/calloc */
  delete[] pDataCpp; /* deallocate buffer allocated with new double[...] */
  mxFree(pMxData);   /* free data created with mx function like mxMalloc */

  mexPrintf("Closing %s and freeing memory...\n",fName);
}

void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
    if (!fp) { tmpnam(fName); fp = fopen(fName,"w"); }
    fprintf(fp,"%d ",++counter);

    if (!pDataC) pDataC = (double*) malloc(sizeof(double)*16);
    if (!pDataCpp) pDataCpp = new double[16];
    if (!pMxData) {
        pMxData = (double*) mxMalloc(sizeof(double)*16);
        mexMakeMemoryPersistent(pMxData); mexPrintf("First!\n");
    }

    mexAtExit(CleanUp);
    // Then use the persistent data...
}

When run:

>> mex -largeArrayDims mexDLLtest.cpp
>> for i=1:5, mexDLLtest; end
First!
>> clear mexDLLtest
Closing \s1rg.1 and freeing memory...
>> type E:\s1rg.1

1 2 3 4 5 

And you have some control over unloading of the file via mexLock and mexUnlock.

What happens to the arguments (i.e. prhs, plhs) when the function starts and returns to MATLAB is very well documented, on the other hand, so I guess that's not what you are asking about.

Regarding multiple instances, you could try using Sysinternals' Process Explorer (if using Window) to have a look at what loaded modules have threads running under MATLAB.exe. I only ever see one instance of a (single threaded) MEX file in threads list no matter how many times or how fast I call the function. However, once back at the command line, you can do version -modules to see a list of loaded modules, as Amro suggested. The MEX file will still be there, and as with the list of threads visible by Process Explorer, I only ever see one instance of a MEX certain file.

Thanks, Amro for the input. I'm interested to see even some more authoritative answers to these questions!



来源:https://stackoverflow.com/questions/20575957/matlab-mex-library-lifecycle

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!