7

我正在用 C++ 开发一个应用程序。该应用程序的组件之一使用 Matlab(通过 Matlab 引擎)进行数据处理。同时,数据采集系统正在将数据流式传输到磁盘。有时,在密集的 Matlab 处理期间,采集系统会崩溃。通过将 Matlab 的处理器亲和性设置为可用处理器的子集,这个问题得到了解决。然而,由于应用程序每天启动几次,并且在多台机器上,每次手动设置亲和度并不方便。通过快捷方式的命令行设置处理器关联的技巧不起作用,因为引擎是从我的应用程序中启动的,而不是通过快捷方式启动的。我一直在寻找一种以编程方式设置亲和力的方法,但收效甚微。

我考虑了以下选项(按优先顺序排列):

  1. 当引擎启动时,从应用程序中指定 matlab 引擎的处理器亲和性。
  2. 为 matlab 引擎指定一个默认的处理器关联,与完整的 Matlab 应用程序本身分开。
  3. 作为最后的手段,为 Matlab 设置默认亲和力(引擎和非引擎使用)。这是最不可取的,因为 Matlab 在部署机器上用于其他目的,最好不要将其限制为其他用途。

是否可以从我的应用程序中设置处理器亲和性,如果可以,如何设置?如果没有,解决这个问题的正确方法是什么?欢迎对这些选项或其他建议/解决方案提出任何建议。

4

3 回答 3

6

听起来你在 Windows 上。您可以直接从 Matlab 调用 .NET 来操作处理器关联掩码,而不必构建 MEX 文件。System.Diagnostics.Process 类具有对处理器关联性的控制,如本解决方案中所述。这是一个使用它的 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。

于 2012-03-20T14:29:40.620 回答
4

我还没有尝试过这个解决方案,但它似乎应该可以工作。创建一个简单的 mex 函数,它执行以下操作:

  1. 调用GetCurrentProcess以检索 MATLAB 进程的句柄
  2. 使用为此过程设置适当的关联掩码SetProcessAffinityMask

现在,当您的应用程序启动时,只需像调用常规 MATLAB 函数一样调用此 mex 函数(mex 函数必须在 MATLAB 路径上可见),并且它应该根据需要设置处理器关联。您甚至可以将关联掩码作为输入传递给函数,以使其更加通用。

于 2012-03-19T21:58:31.553 回答
0

以下是@Praetorian 描述的 MEX 函数的实现(展示了如何使用该SetProcessAffinityMask函数):

set_affinity.c

#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 文档页面中的以下注释:

进程关联由任何子进程或新实例化的本地进程继承。

不要调用SetProcessAffinityMask可能由您自己的进程以外的进程调用的 DLL。

因此,混淆亲和力将影响 MATLAB 及其依赖库启动的所有计算。这是Raymond Chen关于该主题的帖子。

于 2014-06-18T16:15:03.077 回答