C언어 함수를 MEX라는 걸 이용해 변환시켜 매트랩에서 쓸 수 있다.

이때 변환과정에서 C언어 컴파일러가 쓰이는데, 공식적으로 OS X에서 MEX를 사용할 때 Xcode에 있는 clang만 지원한다.

OS 별 MEX 지원 컴파일러는 여기에서 확인할 수 있다.


mex -setup을 입력하면 현재 설정되어 있는 언어와 컴파일러를 확인할 수 있다.


Xcode에 있는 clang은 알다시피 OpenMP를 지원하지 않는다(위의 링크에서도 확인할 수 있다).

OpenMP를 OS X에서 사용하려면 clang-omp를 쓰거나 Xcode용이 아닌 별도의 gcc를 설치해야 하지만(설치 과정은 여기에서 확인),

공식적으로 매트랩에선 지원하지 않는 컴파일러이기 때문에 추가적인 작업이 필요하다.

이번 포스트에서는 그 과정을 설명하고자 한다.


아래의 기준으로 설명한다.

- gcc 6.2.1

- OS X 10.11 El Capitan

- MATLAB R2016b








1. gcc_maci64.xml 만들기


MEX C 컴파일러를 지정해주는 건 매트랩 내에 있는 clang_maci64.xml이라고 하는 파일에 의해서다.

우선 해당 파일부터 열기 위해 파인더에서 다음의 경로로 간다.


/Applications/MATLAB_R2016b.app/bin/maci64/mexopts


mexopts 폴더 안에 3가지가 있는데(C, C++, fortran), 현재 우리는 C언어만 다룬다는 전제이므로 clang_maci64.xml을 복붙하고 이름을 gcc_maci64.xml로 수정한다.

그 후 gcc_maci64.xml을 자신이 쓰고 있는 텍스트 에디터를 통해 연다.


연 뒤 앞쪽에 보면


​Name="Xcode with Clang"

ShortName="Clang"

Manufacturer="Apple"


이라고 되어 있는 부분이 있는데 이는 clang에 관한 내용이므로 gcc에 맞게 알아서 수정한다.

난 아래와 같이 수정했다.


Name="GNU GCC"

ShortName="GCC"

Manufacturer="GNU"


CC의 루트가 clang으로 아래와 같이 지정되어 있는데,


CC="$XCRUN_DIR/xcrun -sdk macosx$SDKVER clang"


이를 gcc 경로로 수정한다. Homebrew로 설치했다면 아래와 같다.


​CC="/usr/local/bin/gcc"


마지막으로, OpenMP를 사용하기 위해 CFLAGS, LDFLAGS 뒤에 -fopenmp를 추가해준다.








2. 매트랩에서 컴파일러 변경하기




매트랩으로 돌아가서 mex -setup을 다시 입력해본다.

입력하면 아래와 같이 나온다.



이전과 다르게 C 컴파일러에서 선택권이 생겼다.

GNU GCC를 클릭한다.



이제 mex를 사용할 때 C 컴파일러는 gcc로 지정이 되었다.

테스트를 해보기 위해 mex test.c를 입력한다.

test.c 코드는 여기에 있는 코드를 사용했고, 내용은 다음과 같다.


#include "mex.h"
#include <stdio.h>
#include "omp.h"

void mexFunction(int nlhs,mxArray* plhs[], int nrhs, const mxArray* prhs[])
{
    int i;
    double sum; 
    /* Check for proper number of arguments. */
    if (nrhs!=0)
    {
        mexErrMsgTxt("No input");
    }
    else if (nlhs!=0)
    {
        mexErrMsgTxt("No output");
    }
    
    omp_set_num_threads(omp_get_max_threads());
    mexPrintf("Max number of threads %d\n",omp_get_max_threads());

    #pragma omp parallel for
    for (i = 0; i < omp_get_max_threads(); i++)
    {
        mexPrintf("Hello from thread %d, nthreads %d\n", omp_get_thread_num(), omp_get_num_threads());
    }
    return; 
}



MEX가 성공적으로 완료되었다고는 하지만 위에 두 개의 에러가 나타난다.

두 개의 에러는 본질적으로는 같은 에러이고, 메세지는 다음과 같은 방식으로 뜬다.


ld: warning: objective file was built for newer OSX version (10.11) than being linked (10.9).


저 에러를 해결할 수 있는 방법을 아직 찾지 못했지만, 당장에 문제가 있지 않아 이대로 두고 사용하고 있다.

나중에 저 에러를 해결하게 되면 포스트를 수정하겠다.


변환된 파일을 실행해보기 위해 test라고 입력해보자.

이 코드는 input, output이 없는 거라 test라고만 입력해도 된다.



MEX로 변환된 파일이 문제없이 잘 작동함을 알 수 있다.








Reference)

https://kr.mathworks.com/support/compilers.html

https://kr.mathworks.com/matlabcentral/newsreader/view_thread/334250

http://stackoverflow.com/questions/37362414/openmp-with-mex-in-matlab-on-mac

+ Recent posts