Установить сродство процессора для MATLAB engine (Windows 7)

Я разрабатываю приложение на C++. Один из компонентов приложения использует Matlab (через движок Matlab) для обработки данных. В то же время система сбора данных передает данные на диск. Иногда, в периоды интенсивной обработки Matlab, система сбора аварийно завершает работу. Установив сродство процессора Matlab к подмножеству доступных процессоров, эта проблема будет решена. Однако, как приложение запускается несколько раз в день, так и на несколько машины, вручную устанавливающие сродство каждый раз неудобно. Трюк установки сродства процессора через командную строку ярлыка не работает, так как движок запускается из моего приложения, а не через ярлык. Я искал способ программно установить сродство, но с ограниченным успехом.

Я рассмотрел следующие варианты (ранжированные в порядке предпочтения):

  1. укажите сродство процессора для движка matlab от в рамках приложения, когда двигатель запущен.
  2. укажите сродство процессора по умолчанию для движка matlab отдельно от полного приложения Matlab.
  3. в крайнем случае установите сродство по умолчанию для Matlab (как двигатель, так и не двигатель использует). Это наименее желательно, так как Matlab используется для других целей на машинах развертывания, и было бы предпочтительнее не ограничивать его для других применений.

можно ли установить сходство процессора из моего приложения, и если да, то как? Если нет, то как правильно решить эту проблему? Любые советы по этим вариантам или другие предложения/решения будут приветствоваться.

3 ответов


звучит так, как будто вы на Windows. Вы можете вызвать .NET непосредственно из Matlab для управления маской сходства процессора и избежать необходимости создавать файл MEX. система.Диагностика.Класс 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 предоставляет объекты библиотеки .NET standard в Windows, иногда можно найдите такие вопросы в C# или .NET и перенесите ответ непосредственно в Matlab.


Я не пробовал это решение, но, похоже, она должна работать. Создайте простую функцию mex, которая делает следующее:

  1. вызов GetCurrentProcess чтобы получить дескриптор для процесса MATLAB
  2. установите соответствующую маску сродства для этого процесса с помощью SetProcessAffinityMask

теперь, когда ваше приложение запускается, просто вызовите эту функцию mex, как обычную функцию MATLAB (функция mex должна быть видна на MATLAB path), и он должен установить сродство процессора, как вы хотите. Вы даже можете передать маску сродства в качестве входа в функцию, чтобы сделать ее более универсальной.


Ниже приведена реализация функции MEX, которая @Praetorian описал (показывает как использовать 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 и его зависимыми библиотеками. Вот a сообщение от Raymond Chen по теме.