我正在用c ++开发一个应用程序。该应用程序的一个组件使用Matlab(通过Matlab引擎)进行数据处理。同时,数据采集系统将数据流传输到磁盘。偶尔,在强化Matlab处理期间,采集系统崩溃。通过将Matlab的处理器亲和性设置为可用处理器的子集,可以解决此问题。但是,由于应用程序每天启动几次,并且在多台计算机上,每次手动设置关联性都很不方便。通过快捷方式的命令行设置处理器关联性的技巧不起作用,因为引擎是从我的应用程序内启动的,而不是通过快捷方式启动的。我一直在寻找一种以编程方式设置亲和力的方法,但成效有限。
我考虑了以下选项(按优先顺序排列):
是否可以在我的应用程序中设置处理器关联,如果可以,如何设置?如果没有,解决这个问题的正确方法是什么?有关这些选项或其他建议/解决方案的任何建议都将受到欢迎。
答案 0 :(得分:6)
听起来像是在Windows上。您可以直接从Matlab调用.NET来操作处理器关联掩码,并避免构建MEX文件。 System.Diagnostics.Process类具有处理器关联性的控件,如in this solution所述。这是一个使用它的Matlab函数。启动它后,首先在Matlab引擎中运行它。
function twiddle_processor_affinity()
proc = System.Diagnostics.Process.GetCurrentProcess();
aff = proc.ProcessorAffinity.ToInt32; % get current affinity mask
fprintf('Current affinity mask: %s\n', dec2bin(aff, 8));
proc.ProcessorAffinity = System.IntPtr(int32(2)); % set affinity mask
fprintf('Adjusted affinity to: %s\n', dec2bin(proc.ProcessorAffinity.ToInt32, 8));
由于Matlab在Windows上公开.NET标准库对象,您有时可以在C#或.NET下搜索这样的问题,并将答案直接传递给Matlab。
答案 1 :(得分:4)
我没有尝试过这个解决方案,但它似乎应该可行。创建一个简单的mex函数,执行以下操作:
GetCurrentProcess
以检索MATLAB过程的句柄SetProcessAffinityMask
现在,当您的应用程序启动时,只需调用此mex函数,就像调用常规MATLAB函数一样(mex函数必须在MATLAB路径上可见),并且应根据需要设置处理器关联。您甚至可以将亲和力掩码作为函数的输入传递给它,以使其更加通用。
答案 2 :(得分:0)
以下是@Praetorian described(显示how to use the SetProcessAffinityMask
function)的MEX函数的实现:
#include "mex.h"
#include <windows.h>
void mexFunction(int nlhs, mxArray* plhs[], int nrhs, const mxArray* prhs[])
{
HANDLE hProc;
DWORD_PTR dwAffinityMask;
unsigned int numCores;
// check arguments
if (nlhs > 0 || nrhs != 1) {
mexErrMsgIdAndTxt("mex:error", "Wrong number of arguments.");
}
if (!mxIsDouble(prhs[0]) || mxGetNumberOfElements(prhs[0])!=1) {
mexErrMsgIdAndTxt("mex:error", "Expecting a scalar number.");
}
// number of logical processors
numCores = (unsigned int) mxGetScalar(prhs[0]);
// set affinity of current process to use all cores
hProc = GetCurrentProcess();
dwAffinityMask = (1 << numCores) - 1;
if (!SetProcessAffinityMask(hProc, dwAffinityMask)) {
mexErrMsgIdAndTxt("mex:error", "WinAPI error code: %lu", GetLastError());
}
}
在我的四核超线程机器上,我将调用MEX函数,如下所示,以允许MATLAB在所有8个逻辑处理器上执行:
>> getenv('NUMBER_OF_PROCESSORS')
ans =
8
>> mex -largeArrayDims set_affinity.c
>> set_affinity(8)
仅使用处理器数量的一半:
>> set_affinity(4)
请注意MSDN doc page中的以下注释:
进程关联性由任何子进程或新进程继承 实例化的本地流程。
不要在可能被调用的DLL中调用
SetProcessAffinityMask
除了你自己以外的其他过程。
因此,使用关联性会影响MATLAB及其依赖库启动的所有计算。这是关于该主题的a post by Raymond Chen。