green_fr: (Default)
green_fr ([personal profile] green_fr) wrote2018-01-17 09:42 am

Оптимизация кода

Объяснил коллеге, зачем нужно преаллокация памяти. Понимаешь, говорю, если добавлять строчку за строчкой в матрицу, то каждый раз MatLab ищет новое место в памяти, копирует туда уже сделанную матрицу и дописывает новую строчку. А если ты сразу сказал ему, сколько у тебя будет строчек — он сразу столько выделил и ничего никуда не копирует.
Понял? Понял!

Сегодня просматриваю написанный им код. В одном месте ему нужна переменная, которую он запишет в Excel. Размер заранее посчитать нетривиально. Преаллокация на 500000 (пятьсот тысяч) строк, из которых реально заполняется две с чем-то тысячи. Команда записи этой матрицы в Excel рушит мой комп...

[identity profile] grave--digger.livejournal.com 2018-01-17 09:19 am (UTC)(link)
Какой хороший человек, однако! :)
Edited 2018-01-17 09:20 (UTC)

[identity profile] green-fr.livejournal.com 2018-01-17 10:12 am (UTC)(link)
Мне искренне интересно, как он закоммитил этот код, не проверяя! У него комп не мощнее моего.

[identity profile] birdwatcher.livejournal.com 2018-01-17 09:38 am (UTC)(link)
Я думаю, в следующих версиях матлаба это неудобство исправят и перейдут на ленивую преаллокацию: будут на требование зарезервировать 500000 строк ничего не делать и мгновенно возвращать успех; а потом внутри по мере надобности добавлять по одной строчке.

[identity profile] green-fr.livejournal.com 2018-01-17 10:14 am (UTC)(link)
Этого я сам жду недождусь. Не по строчке, конечно, а какими-то разумными блоками, и чтобы в конце аккуратно обрезались неиспользованные строки.

[identity profile] birdwatcher.livejournal.com 2018-01-17 10:43 am (UTC)(link)
А у тебя есть объяснение происходящему? В смысле, зачем в 2017 г. использовать для работы связку матлаб/эксел?

[identity profile] green-fr.livejournal.com 2018-01-17 01:09 pm (UTC)(link)
У нас я знаю зачем - считаем всё в MatLab, а результаты потом рассылаем в Excel.

(проблема аллокации матриц при этом остаётся, даже если вычеркнуть Excel из связки)

[identity profile] green-fr.livejournal.com 2018-01-17 01:32 pm (UTC)(link)
А что не так-то? Ты предполагал, что мы будет распечатывать результаты на бумаге и рассылать?

[identity profile] birdwatcher.livejournal.com 2018-01-17 01:50 pm (UTC)(link)
Это отдельный интересный вопрос, в каком виде распространять таблицы, и зачем. Если для печати - наверно, это должен быть pdf. Если для динамического доступа на экране - наверное, вебсайт. Эксел, по-моему, не относится к полезным способам репрезентации чего бы то ни было.

[identity profile] muh2.livejournal.com 2018-01-17 02:16 pm (UTC)(link)
Из моего опыта, если в воздухе пахнет деньгами - относится. Более того - становится основным.

[identity profile] green-fr.livejournal.com 2018-01-17 02:47 pm (UTC)(link)
В данном конкретном случае - для того, чтобы передать этот Excel третьей программе, у которой есть кнопка "Load data from Excel file" :-)
Я думаю, тебе понравится тот факт, что эту программу нам поставила Еврокомиссия в рамках нового закона по контролю страховы компаний :-Р

[identity profile] birdwatcher.livejournal.com 2018-01-17 02:50 pm (UTC)(link)
Ну вот, так бы и говорил.

[identity profile] green-fr.livejournal.com 2018-01-17 03:02 pm (UTC)(link)
А если чуть серьёзнее - у нас есть, например, отслеживание в Excel каждой версии программы MatLab. Программа MatLab генерит какое-то невообразимое количество данных, но основные показатели можно вывести на одну страницу. Обычно да, её просто распечатывают. Но для отслеживания версий удобно её сохранять в отдельной закладке Excel, чтобы можно было сразу увидеть эволюцию каждого из отслеживаемых параметров с каждой версией программы. Удобная вещь.

Плюс, есть огромное количество людей, которым проще манипулировать данными именно в Excel - для них мы тоже результаты сводим в один файл и отсылаем. То есть это могут быть промежуточные данные, но продолжение рассчётов находится вне нашего отдела, а Excel - это такая lingua franca при общении на разных языках (у нас есть ещё один актуарный отдел, который считает в SAS, и третий на VB.NET).

[identity profile] birdwatcher.livejournal.com 2018-01-17 03:13 pm (UTC)(link)
Жуткая кибернетическя антиутопия. Кто-то отправился в прошлое и наступил на бабочку, и теперь надо пользоваться SAS поверх .NET.

[identity profile] muh2.livejournal.com 2018-01-17 11:00 am (UTC)(link)
Что такое строчка?

А то 5е5 указателей зарезервировать - не проблема. Если честно, то и 5е5 256 байтных строк - тоже не проблема.

[identity profile] green-fr.livejournal.com 2018-01-17 01:11 pm (UTC)(link)
Если бы оно работало, я бы даже не заметил этой строчки, наверное. Но оно же пытается записать 500000 пустых строк в Excel. То есть создать структуру на 500000 строк, в которых нет ничего. И вот здесь, видимо, тоже талантливые люди писали код, потому что эта операция не проходит на 16GB RAM. Памяти не хватает.

[identity profile] muh2.livejournal.com 2018-01-17 01:27 pm (UTC)(link)
Это я понимаю. Я не понимаю - что такое "строка". Какой длины? Это может быть указатель в 4 байта. Указатель на структуру байт в 8. Видывал я строки по умолчанию в 256 байт. Но может это и 2^16 байт. Тогда может и зашкалить. А так-то 5е5 это всего лишь 0.0005 Гига.

[identity profile] green-fr.livejournal.com 2018-01-17 01:33 pm (UTC)(link)
В данном случае - это "строка Excel". Очень растяжимое понятие. Особенно, если её представляет не сам Excel, а сторонняя (в данном случае MathWorks) библиотека. Сколько съедает одна строка памяти - это уже на совести разработчика.

[identity profile] fima.livejournal.com 2018-01-17 07:20 pm (UTC)(link)
едва ли матлаб так работает. или я значительно преувеличиваю умственные способности разработчиков.

[identity profile] green-fr.livejournal.com 2018-01-17 09:01 pm (UTC)(link)
Не хотелось тебя расстраивать, но этот совет фигурирует на первом месте их же собственных советов как ускорить ваш код (https://fr.mathworks.com/help/matlab/matlab_prog/techniques-for-improving-performance.html)...

[identity profile] fima.livejournal.com 2018-01-18 07:56 am (UTC)(link)
ну там, мне кажется, не сказано, что матлаб переаллокирует с добавлением каждого элемента, скорее всего он преаллокирует какое-то количество когда места не остается и скорее всего он удваивает количество места с каждой переаллокацией как делают все обычные программы. поэтому, если заранее известно количество элементов, то преаллокация помогает, если нет - то в среднем мешает, о чем ярко свидетельствует опыт твоего коллеги.

[identity profile] green-fr.livejournal.com 2018-01-18 08:39 am (UTC)(link)
Кстати да, задумался, откуда у меня информация о преаллокации после каждого элемента...

Прогнал тест. С увеличением в 10 раз количества элементов время, затраченное с преаллокацией увеличивается в 10 раз (логично), но и без преаллокации тоже увеличивается в 10 раз. То есть, отношение остаётся постоянным (в моём примере примерно 1:15). Так что, похоже, ты прав - в моём случае зависимость была бы не линейной, а квадратичной, и отношение времени с преаллокацией : без преаллокации росло бы.

[identity profile] fima.livejournal.com 2018-01-18 09:13 am (UTC)(link)
почему квадратичной?
в тесте ты смешиваешь замеры времени переаллокации и выполнения полезной работы (запись данных). твое соотношение 1:15 очень странное, говорит о том, что матлаб делает еще какую-то чудовищную побочную работу либо переаллокирует как-то сильно через жопу (например, перепроверяет каждую ячейку). если бы он занимался только переаллокацией и записью, то замедление без преаллокации должно было быть несколько процентов максимум, а не в разы.

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

я тут слушал лекцию на ютубе про оптимизацию обработки в программах биржевого трейдинга. все идеи надо тестировать на конкретной задаче, практически невозможно предугадать ускорит или замедлит та или иная идея оптимизации выполнение задачи. процессор работает очень хитро, как мы теперь узнали после сообщений о meltdown и spectre.

[identity profile] green-fr.livejournal.com 2018-01-18 10:34 am (UTC)(link)
Блочной аллокации у него точно нет, про это я читал какие-то их технические статьи, когда нарвался на проблему с дефрагментацией RAM. Мы из-за этого переходили на 64-битную архитектуру, потому что MathWorks нам сказал, что в 32-битной (не помню, у них ли, или у Windows) нет дефрагментации, а в 64-битной есть. А у нас регулярно вылетало out of memory при попытке аллокации матрицы на 200 МБ, например, при свободных (и доступных MatLab) 600 МБ. И проблема зачастую решалась перезагрузкой, после которой память дефрагментировалась автоматически.
Вот в этот момент они чётко рассказали, что каждая матрица у них должна занимать последовательные ячейки памяти.

А про масштаб 1:15 - да, я как-то не задумывался о его вменяемости. Но в примере по ссылке выше у MathWorks примерно такой же результат.

Квадратичный - потому что, если ты переаллокируешь каждые X строчек, и каждый раз копируешь уже накопленные данные, то операция копирования (я предполагаю, что именно она занимает время) будет рости квадратично с размером матрицы. Грубо говоря, ты копируешь 1 строку, потом 2, потом 3 и т.д., а сума арифметической прогрессии - это квадрат. А если аллокация каждые 2^n строчек (как предположил ты), то сумма степенного ряда даст 2^(n+1). То есть, линейный рост с ростом изначальной матрицы.

[identity profile] fima.livejournal.com 2018-01-18 11:19 am (UTC)(link)
перезагрузка винды для дефрагментации памяти приложения? сколько в мире удивительных вещей!

[identity profile] green-fr.livejournal.com 2018-01-18 10:38 am (UTC)(link)
В такой формулировке (последнего параграфа) я полностью согласен. Но с моими коллегами (описанный мною коллега пишет больше и лучше всех остальных) можно инвертировать фразу, и смысл её поменяется. Да, сложно предугадать, какой метод оптимизации будет лучше. Но зачатую можно с лёгкостью сказать, какая чушь гарантированно замедлит рассчёт. Я регулярно вычёркиваю из проекта тупо дублирующие друг друга рассчёты - не надо быть гением, чтобы понять влияние (не несущего никакого дополнительного смысла) дублирования кода на скорость рассчётов :-)

[identity profile] zlyuk.livejournal.com 2018-01-18 04:24 pm (UTC)(link)

есть такая старинная русская пословица: заставь дурака строить таблицу...


разве таблицы в несколько тысяч строк так ощутимо тормозят матлаб,что это имеет смысл?

[identity profile] green-fr.livejournal.com 2018-01-18 07:23 pm (UTC)(link)
Тормоза я даже не мерил, но команда xlswrite просто падает с такими таблицами :-)