Matlab mex file медленнее по сравнению с его прямым C-эквивалентом
Я затрудняюсь объяснить (и избежать) различий в скорости между Mex-программой Matlab и соответствующей C-программой без интерфейса Matlab. Я профилировал программу численного анализа:
int main(){
Well_optimized_code();
}
скомпилировано с gcc 4.4 против эквивалента Matlab-Mex (направлено на использование gcc44, который в настоящее время не поддерживается Matlab, но требуется по другим причинам):
void mexFunction(int nlhs,mxArray* plhs[], int nrhs, const mxArray* prhs[]){
Well_optimized_code(); //literally the exact same code
}
Я выполнил время как:
$ time ./C_version
против
>> tic; mex_version(); toc
Разница во времени ошеломляет. Запуск версии из командной строки занимает в среднем 5,8 секунды. Версия в Matlab запускается за 21 секунду. Для контекста, mex-файл заменяет алгоритм в наборе инструментов SimBiology, запуск которого занимает около 26 секунд.
По сравнению с алгоритмом Matlab версии C и Mex линейно масштабируются до 27 потоков, используя вызовы openMP, но в целях профилирования эти вызовы были отключены и закомментированы.
Две версии были скомпилированы одинаковым образом, за исключением необходимых флагов для компиляции в виде mex-файла: -fPIC --shared -lmex -DMATLAB_MEX_FILE, применяемый в mex-компиляции / компоновке. Я удалил все ссылки на левый и правый аргументы mex-файла. То есть он не принимает входные данные и не дает никаких выходных данных, он предназначен исключительно для профилирования.
Великий и славный Google сообщил мне, что независимый от позиции код не должен быть источником замедления, и кроме этого я в растерянности.
Любая помощь будет оценена,
Эндрю
2 ответа
После месяца переписки по электронной почте с моими контактами в Mathworks, игры со своим собственным кодом и профилирования моего кода в любом случае, у меня есть ответ; однако, это может быть самый неудовлетворительный ответ, который я когда-либо имел на технический вопрос:
Короткая версия - "обновление до версии Matlab 2011a (официально выпущенной на прошлой неделе), эта проблема теперь решена".
Более длинная версия касается проблемы издержек, связанных со шлюзом mex в версиях 2010b и более ранних. Лучшее объяснение, которое я смог извлечь, состоит в том, что эти накладные расходы не оцениваются один раз, а мы платим немного каждый раз, когда функция вызывает другую функцию, которая находится в связанной библиотеке.
Хотя то, почему это происходит, сбивает меня с толку, это, по крайней мере, согласуется с профилированием SHARK, которое я сделал. Когда я профилирую и сравниваю различия между нативным и мекс-приложением, возникает повторяющаяся картина. Время, потраченное на функции из исходного кода, который я написал для приложения, не меняется. Время, затрачиваемое на библиотечные функции, немного увеличивается при сравнении нативных и мексиканских реализаций. Функции в другой библиотеке, используемые для создания этой библиотеки, значительно увеличивают разницу. Разница во времени продолжает увеличиваться, поскольку мы продвигаемся все глубже, пока не достигнем реализации BLAS.
Несколько сильно используемых функций BLAS были главными виновниками. Функция, которая занимала ~1% моего времени вычислений в нативном приложении, работала на 30% в функции mex.
Реализация шлюза mex, кажется, изменилась между 2010b и 2011a. На моем macbook нативное приложение занимает около 6 секунд, а версия mex - 6,5 секунды. Это накладные расходы, с которыми я могу иметь дело.
Что касается первопричины, я могу только догадываться. Matlab имеет свои корни в интерпретирующем кодировании. Поскольку мекс-функции являются динамическими библиотеками, я предполагаю, что каждая мекс-библиотека не знала, с чем она была связана, до времени выполнения. Поскольку Matlab предлагает пользователю редко использовать mex и только для небольших вычислительных блоков, я предполагаю, что большие программы (такие как решатель ODE) реализуются редко. Эти программы, как и моя, страдают больше всего.
Я профилировал несколько функций Matlab, которые, как мне известно, были реализованы в C, а затем скомпилированы с использованием mex (особенно sbiosimulate после вызова sbioaccelerate для кинетических моделей, часть набора инструментов SimBiology), и, похоже, произошли некоторые существенные повышения. Таким образом, обновление 2011a представляется более полезным, чем обычное полугодовое обновление.
Желаем удачи другим программистам с похожими проблемами. Спасибо за все полезные советы, которые помогли мне начать в правильном направлении.
--Эндрю
Напомним, что Matlab хранит массивы как основные столбцы, а C/C++ - как основные строки. Возможно ли, что ваша структура / алгоритм цикла итеративно проходит ряды строк, что приводит к плохому времени доступа к памяти в Matlab, но к быстрому времени доступа в C/C++?