Семафоры и замки в MATLAB

Я работаю над проектом MATLAB, где мне бы хотелось, чтобы два экземпляра MATLAB выполнялись параллельно и совместно использовали данные. Я назову эти экземпляры MAT_1 и MAT_2. Более конкретно, архитектура системы:

  • MAT_1 последовательно обрабатывает изображения, читая их один за другим, используя imread, и выводит результат для каждого изображения с помощью imwrite.
  • MAT_2 считывает изображения, выводимые с помощью MAT_1 с помощью imread, и выводит результат в другом месте.

Одна из проблем, которые, как мне кажется, мне нужно решить, состоит в том, чтобы гарантировать, что MAT_2 считывает вывод изображения с помощью MAT_1 после того, как MAT_1 полностью завершит запись на него.

Мои вопросы:

  • Как вы подходите к этой проблеме? Нужно ли использовать семафоры или блокировки для предотвращения условий гонки?
  • Предоставляет ли MATLAB механизм блокировки файлов? (т.е. что-то похожее на flock, но предоставлено MATLAB напрямую, и это работает на нескольких платформах, например Windows и Linux). Если нет, знаете ли вы о какой-либо сторонней библиотеке, которую я могу использовать для создания этого механизма в MATLAB?

EDIT:

  • Как отмечает @yoda, Parallel Computing Toolbox (PCT) позволяет блокировать вызовы между работниками MATLAB, что отлично. Тем не менее, меня особенно интересуют решения, которые не требуют PCT.
  • Зачем мне нужны MAT_1 и MAT_2 для запуска в параллельных потоках?:

    Обработка, выполняемая в MAT_2, в среднем медленнее (и более подвержена сбою), чем MAT_1, а вывод MAT_1 подает другие программы и процессы (включая проверку человека), которые не нужно ждать MAT_2 выполнить свою работу.

Ответы:

  • Для решения, которое позволяет реализовать семафоры, но не полагается на PCT, см. ответ Йонаса ниже
  • Для других хороших подходов к проблеме см. ниже ответ Yoda

Ответ 1

Лично я использую для этого панель инструментов параллельной обработки.

Насколько я знаю, в Matlab нет простого способа иметь системные блокировки файлов. Однако, чтобы гарантировать, что Matlab # 2 только считывает вывод Matlab # 1, когда файл закончил запись, я предлагаю, чтобы после записи, например, файла results_1.mat, Matlab # 1 записывает второй файл results_1.finished, который пустой текстовый файл. Поскольку второй файл записывается после первого, его существование сигнализирует, что файл результатов был записан. Таким образом, вы можете искать файлы с расширением finished, т.е. dir('*.finished'), и использовать fileparts для получения имени файла .mat, который вы хотите загрузить с помощью Matlab # 2.

Ответ 2

Я бы применил это с помощью семафоров; по моему опыту, PCT необоснованно медленна при синхронизации.

dfacto (другой ответ) имеет большую реализацию семафоров для MATLAB, однако он не будет работать в MS Windows; Я улучшил эту работу, чтобы это было так. Улучшенная работа здесь: http://www.mathworks.com/matlabcentral/fileexchange/45504-semaphoreposixandwindows

Это будет лучше, чем взаимодействие с Java,.NET, PCT или файлами. Это не использует Parallel Computing Toolbox (PCT), и функциональность семафора AFAIK в любом случае не входит в PCT (недоумевая, что они их оставили!). Можно использовать PCT для синхронизации, но все, что я пробовал в этом, было неоправданно медленным.

Чтобы установить эту высокопроизводительную библиотеку семафора в MATLAB, запустите ее в интерпретаторе MATLAB: mex -O -v semaphore.c

Вам понадобится компилятор С++ для компиляции semaphore.c в двоичный MEX файл. Этот MEX файл затем может быть вызван из вашего кода MATLAB, как показано в примере ниже.

Пример использования:

function Example()
    semkey=1234;
    semaphore('create',semkey,1);
    funList = {@fun,@fun,@fun};
    parfor i=1:length(funList)
        funList{i}(semkey);
    end
end
function fun(semkey)
    semaphore('wait',semkey)
    disp('hey');
    semaphore('post',semkey)
end

Ответ 3

Я не уверен, что вы ищете решение только для Matlab, но я только что представил семафорную оболочку для использования в Matlab. Он работает как общий семафор, но в основном он был разработан с sharedmatrix.

Как только Mathworks примет заявку, я обновлю ссылку в моей группе исследований .

Обратите внимание, что этот mex файл является оболочкой для функции семафора POSIX. Как таковой он будет работать в Linux, Unix, MacOS, но не будет работать из коробки в Windows. Он может работать при компиляции с библиотеками cygwin.

Ответ 4

Я не думаю, что существует отличный способ, кроме использования специальных блокировок ОС. Один из подходов может заключаться в том, чтобы MAT_1:

imwrite(fileName);
movefile(fileName, completedFileName);

И у MAT_2 только процесс завершенFileName.

Ответ 5

EDIT:

После просмотра вашего редактирования простым решением, не связанным с использованием каких-либо наборов инструментов, является следующее:

Так как MAT_2 намного медленнее, чем MAT_1, запустите MAT_2 с задержкой. то есть запустить его, когда MAT_1 завершит обработку, скажем, 5 изображений или около того. Если вы это сделаете, MAT_2 никогда не догонит MAT_1 и, следовательно, никогда не будет в ситуации, когда он должен "ждать" изображений с MAT_1.


Я до сих пор не понимаю некоторые моменты из вашего вопроса:

  • Вы говорите, что MAT_1 обрабатывает изображения последовательно, но нужно ли это? Другими словами, имеет ли смысл порядок, в котором они обрабатываются?
  • Вы говорите, что MAT_2 читает вывод из MAT_1... Должен ли он быть в том порядке, в котором MAT_1 заканчивается или может быть любым порядком?
  • Вы говорите, что MAT_2 читает изображение с помощью imread и выводит его где-то еще. Есть ли причина, по которой эта задача не может быть объединена в MAT_1?

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

Важно отметить, что каждый рабочий (лаборатория) имеет labindex, и вы можете использовать labSend отправить работнику 1 (эквивалент MAT_1) работнику 2 (эквивалент MAT_2), который затем получает его с помощью labReceive. Из документации по labReceive:

Эта функция блокирует выполнение в лаборатории до тех пор, пока соответствующий вызов labSend не появится в отправляющей лаборатории.

что в значительной степени связано с тем, что вы хотели сделать с MAT_1 и MAT_2.

Другой способ сделать это - это создать еще одного рабочего в текущем сеансе, но назначить ему только те задачи, которые выполняются MAT_1. Затем вы устанавливаете свойство FinishedFcn для выполнения задач, выполняемых набором функций, выполняемых MAT_2, но я бы не рекомендовал его как Я не думаю, что это было намерение для FinishedFcn, и я не знаю, будет ли он прерываться в некоторых случаях.

Ответ 6

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

В нечетном случае, когда нет такой вещи, вы можете также посмотреть на разные среды, чтобы реализовать то, что вы хотите. Это может быть немного обходным путем, но вы всегда можете связать свой код MATLAB с другими языками (например, Java,.NET, C,...) и использовать те функциональные возможности, к которым вы привыкли. С Java вы совершенно уверены, что ваше решение не зависит от платформы,.NET работает только с Windows (по крайней мере, в сочетании с MATLAB).