Matlab中的多CPU并行计算:一种基于Matlab引擎的混合编程

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

Matlab中的多CPU并行计算:一种基于Matlab引擎的混合编程


实验室新购置了一台双核本本,就忍不住琢磨一下,好使得我那Matlab下的程序更有效率。然而Google下来却收获甚微,有朋友提到可以使用Matlab的Distribution Computing Toolbox,但似乎是用于多台电脑联网时的情况,与我的要求相差甚远。因此只好自己鼓捣一下,借此机会抛砖引玉,欢迎大家共同探讨。

方法思路非常清晰:使用C和Matlab混合编程的方法,在C中用线程启动Matlab引擎,如此就可以启动多个程序,充分发挥多核CPU的优势。

在这里给出一个简单的示例程序,其线程任务为通过随机数方法来计算pi(就是为了拖时间)。

示例一共由4个文件构成:

ThreadDemo.cpp: 主程序

compopts.bat: 编译配置文件

Thread1.m: 计算pi的程序

disp2.m: 辅助显示程序

只需在Matlab环境下调用mbuild -f compopts.bat -v ThreadDemo.cpp命令即可生成可执行文件ThreadDemo.exe,再输入命令!ThreadDemo即可观察结果。实验环境为在Matlab6.5, VC6.0。Matlab7.0由于对混合编程的方式进行了较大改动,示例可以通过编译,但不能正常运行。

以下为运行结果:

>> !ThreadDemo

10:41:32 --> Time used: 27", 10:41:05 -- 10:41:32

10:41:32 --> Task1: IterNum = 100000000, Result = 3.141961

10:41:33 --> Time used: 27", 10:41:06 -- 10:41:33

10:41:33 --> Task2: IterNum = 100000000, Result = 3.141961

可以看到两个任务几乎同时启动,同时结束。运行时可以看到打开了两个独立的Matlab引擎(随后被隐藏),CPU占用率100%,共耗时28s。如果单独运行两个任务,则分别需要25s。考虑到引擎启动及数据传输的时间,这个结果还是比较合理的。

随后附上各文件,也可从附件直接下载。由于代码较为简单,就不多做解释了,大家看看就明白了。

上文给出的是使用mbuild生成独立程序的方法,类似的我们也可以使用mex来生成Matlab中调用的dll,也有相同效果。

-----------------------------------------------------------------------------------

ThreadDemo.cpp

/**********************************************************

run the following command to generate executable file

>> mbuild -f compopts.bat -v ThreadDemo.cpp

**********************************************************/

#include

#include

#include

#include

#include

#include "engine.h"

#include "matlab.hpp"

typedef enum{

MAT_TASK1,

MAT_TASK2

} EMatTask;

const int BUF_SIZE = 1024;

bool bTask1 = 0;

bool bTask2 = 0;

void MatTask(void *pTaskID)

{

const double IterNum1 = 10e7;

const double IterNum2 = 10e7;



char strInfoBuf[BUF_SIZE];



EMa

tTask TaskID;



Engine *ep;

mxArray *T = NULL;



if (!(ep = engOpenSingleUse("\0", NULL, NULL))) {

fprintf(stderr, "\nCan't start MATLAB engine\n");

return;

}



engSetVisible(ep, 0);

engOutputBuffer(ep, strInfoBuf, BUF_SIZE);



engEvalString(ep, "cd E:\\Work\\Program\\Matlab\\Test\\TestThread");

TaskID = *((EMatTask *)pTaskID);

if(TaskID == MAT_TASK1)

{

T = mxCreateDoubleMatrix(1, 1, mxREAL);

memcpy((void *)mxGetPr(T), (void *)(&IterNum1), sizeof(double));

engPutVariable(ep, "T", T);



engEvalString(ep, "y = Thread1(T);");

printf("%s", strInfoBuf);



engEvalString(ep, "disp2(sprintf('Task1: IterNum = %d, Result = %f', T, y));");

printf("%s", strInfoBuf);



bTask1 = 1;

}

else if(TaskID == MAT_TASK2)

{

T = mxCreateDoubleMatrix(1, 1, mxREAL);

memcpy((void *)mxGetPr(T), (void *)(&IterNum2), sizeof(double));

engPutVariable(ep, "T", T);



engEvalString(ep, "y = Thread1(T);");

printf("%s", strInfoBuf);



engEvalString(ep, "disp2(sprintf('Task2: IterNum = %d, Result = %f', T, y));");

printf("%s", strInfoBuf);



bTask2 = 1;

}



// engEvalString(ep, "whos");

// printf("%s", strInfoBuf);



engClose(ep);

}

void main()

{

EMatTask TaskID1, TaskID2;



bool bThreadMode = 1;



TaskID1 = MAT_TASK1;

TaskID2 = MAT_TASK2;



if(!bThreadMode)

{

MatTask((void *)&TaskID1);

MatTask((void *)&TaskID2);

}

else

{

_beginthread( MatTask, 0, (void *)&TaskID1 );

_beginthread( MatTask, 0, (void *)&TaskID2 );



while(!(bTask1 & bTask2))

{

Sleep(100);

}

}

}

----------------------------------------------------------------------------------

compopts.bat

@echo off

rem MSVC60COMPP.BAT

rem

rem Compile and link options used for building MATLAB compiler programs

rem with Microsoft Visual C++ compiler version 6.0

rem

rem $Revision: 1.18 $ $Date: 2002/03/29 16:30:16 $

rem

rem ********************************************************************

rem General parameters

rem ********************************************************************

set MATLAB=%MATLAB%

set MSVCDir=D:\Program Files\Microsoft Visual Studio\VC98

set MSDevDir=%MSVCDir%\..\Common\msdev98

set PATH=%MSVCDir%\BIN;%MSDevDir%\bin;%MATLAB_BIN%;%PATH%

set INCLUDE=%MSVCDir%\INCLUDE;%MSVCDir%\MFC\INCLUDE;%MSVCDir%\ATL\INCLUDE;%INCLUDE%

set LIB=%MSVCDir%\LIB;%MSVCDir%\MFC\LIB;%LIB%

set PERL="%MATLAB%\sys\perl\win32\bin\perl.exe"



rem ********************************************************************

rem Compiler parameters

rem ********************************************************************

set COMPILER=cl

set OPTIMFLAGS=-O2 -DNDEBUG

set DEBUGFLAGS=-Zi -Fd"%OUTDIR%%MEX_NAME%.pdb"

set CPPOPTIMFLAGS=-O2 -DNDEBUG

set CPPDEBUGFLAGS=-Zi -Fd"%OUTDIR%%MEX_NAME%.pdb"

set COMPFLAGS=-c -MT -D"_X86_" -Zp8 -G5 -W3 -nologo

set CPPCOMPFLAGS=-c -Zp8 -G5 -W3 -nologo -Zm500 -GX -MD -I"%MATLAB%\extern\include\cpp" -DMSVC -DIBMPC -DMSWIND

set DLLCOMPFLAGS=-c -Zp8 -G5 -W3 -nologo -DMSVC -DIBMPC -DMSWIND

set NAME_OBJECT=/Fo

rem ********************************************************************

rem Library creation commands creating import and export libraries

rem ********************************************************************

set DLL_MAKEDEF=type %BASE_EXPORTS_FILE% | %PERL% -e "print \"LIBRARY %MEX_NAME%.dll\nEXPORTS\n\"; while (<>) {print;}" > %DEF_FILE%

rem ********************************************************************

rem Linker parameters

rem MATLAB_EXTLIB is set automatically by mex.bat

rem ********************************************************************

set LIBLOC=%MATLAB%\extern\lib\win32\microsoft\msvc60

set LINKER=link

set LINKFLAGS=kernel32.lib user32.lib gdi32.lib advapi32.lib oleaut32.lib ole32.lib /LIBPATH:"%LIBLOC%" libmmfile.lib libmatlb.lib libeng.lib /nologo

set LINKFLAGS=%LINKFLAGS% libmx.lib libmat.lib libmwservices.lib libmex.lib libut.lib

set CPPLINKFLAGS=%MATLAB_EXTLIB%\libmatpm.lib

set DLLLINKFLAGS= %LINKFLAGS% /dll /implib:"%OUTDIR%%MEX_NAME%.lib" /def:%DEF_FILE%

set HGLINKFLAGS=sgl.lib libmwsglm.lib

set LINKOPTIMFLAGS=

set LINKDEBUGFLAGS=/debug

set LINK_FILE=

set LINK_LIB=

set NAME_OUTPUT="/out:%OUTDIR%%MEX_NAME%.exe"

set DLL_NAME_OUTPUT="/out:%OUTDIR%%MEX_NAME%.dll"

set RSP_FILE_INDICATOR=@

rem ********************************************************************

rem Resource compiler parameters

rem ********************************************************************

set RC_COMPILER=rc /fo "%OUTDIR%%RES_NAME%.res"

set RC_LINKER=

rem ********************************************************************

rem IDL Compiler

rem ********************************************************************

set IDL_COMPILER=midl /nologo /win32 /I "%MATLAB%\extern\include"

set IDL_OUTPUTDIR= /out "%OUTDIRN%"

set IDL_DEBUG_FLAGS= /D "_DEBUG"

set IDL_OPTIM_FLAGS= /D "NDEBUG"

set POSTLINK_CMDS1=if exist %LIB_NAME%.def del %LIB_NAME%.def

----------------------------------------------------------------------------------

Thread1.m

function p = Thread1(N)



t1 = clock;

strT1 = datestr(now,'HH:MM:SS');



count = 0;

for k = 1:N

x = 2 * rand - 1;

y = 2 * rand - 1;

if(sqrt(x^2 + y^2) <= 1)

count = count + 1;

end;

en

d;

p = 4.0 * count / N;

t2 = clock;

strT2 = datestr(now,'HH:MM:SS');

t = etime(t2,t1);

mins = floor(t / 60);

secs = round(mod(t,60));

if(mins == 0)

disp2(sprintf('Time used: %d", %s -- %s',secs,strT1,strT2));

else

disp2(sprintf('Time used: %d''%d"(%.3fs), %s -- %s',mins,secs,t, strT1,strT2));

end;



----------------------------------------------------------------------------------

disp2.m

function disp2(str, DispMask, CurrMask)

if( (~exist('DispMask')) & (~exist('CurrMask')) )

disp(strcat(datestr(now,'HH:MM:SS'), ' -->', sprintf(' %s', str)));

return;

end;

if(bitand(DispMask, CurrMask))

disp(strcat(datestr(now,'HH:MM:SS'), ' -->', sprintf(' %s', str)));

end;

----------------------------------------------------------------------------------


相关文档
最新文档