green_fr: (Default)
[personal profile] green_fr
Продолжаю копать недавний вопрос, довёл ситуацию до минимализма, и всё равно ничего не понимаю.

Есть некий скрипт, который выглядит примерно* так:
a = random(...);
b = random(...);
for i = 1 : 1000
    a = a + b;
end

1. Запускаю его на своём компе — память загружена на некотором уровне X, процессор загружен на 25% (у меня 4 ядра, MatLab крутится на одном из них), время работы цикла 19 секунд.
2. Запускаю два MatLab, на каждом из них запускаю ручками копию этого скрипта. Память загружена вдвое больше (логично), процессор загружен на 50% (логично), время работы цикла 34 секунды (я ждал, очевидно, 19 секунд).

В чём фишка? Единственное разумное объяснение — меня ограничивает скорость чтения / записи RAM. В это не хочется верить, и как минимум хочется поверить.

Откуда следующие вопросы:
1. Как получить максимальную скорость чтения / записи RAM? Измерить / посчитать по техническим характеристикам / запустить утилиту.
2. Как посмотреть реальную скорость работы с RAM? В идеале иметь такой монитор, как Task Manager, который рисовал бы график в реальном времени, чтобы на нём глазами увидеть потолок, об который стучится мой процесс. Наш IT выслушал, попробовал две какие-то стандартные у них утилиты и развёл руками. Hotline MatLab вообще вопроса не понял (провёл с ними час по телефону, зол неописуемо).
3. (в голову как-то не лезет, что программу тормозит RAM, с детства привыкли, что у него скорость, конечно, ограниченная, но это только в теории) Какие ещё есть варианты объяснения этого эффекта?


*Скрипт выглядит «примерно» так, т.к. MatLab в принципе иногда работает с несколькими ядрами процессора. Например, простую операцию a + b он легко раскидывает на несколько ядер. А вот bsxfun(@plus, a, b), позволяющую складывать матрицы разного размера, уже не раскидывает. Поэтому для простоты я написал +, но на самом деле там bsxfun.

Date: 2014-03-18 07:37 pm (UTC)
From: [identity profile] birdwatcher.livejournal.com
Процессорный кеш же.

Date: 2014-03-18 09:12 pm (UTC)
From: [identity profile] green-fr.livejournal.com
Так а что кеш? Я с трудом представляю, как он на этих масштабах работает, но сдаётся мне, что толку от него ноль, он будет тупо туда-сюда переписываться, причём в обоих вариантах — что две матрицы, что четыре, слишком много для кэша. Нет? Ты не это хотел сказать?

Date: 2014-03-18 09:20 pm (UTC)
From: [identity profile] birdwatcher.livejournal.com
Ну там же еще где-то интерпретаторы обоих матлабов должны жить. Вообще, с моей колокольни, довольно экзотично разгонять матлаб, ты же не торгуешь из него.

Date: 2014-03-19 11:59 am (UTC)
From: [identity profile] voldemar.livejournal.com
Ага, в том-то и дело, что матрицы не влазят целиком в кэш. Процы готовы молотить цифры с куда большей производительностью, чем память готова их подавать и записывать обратно. Кэш помогает помогает показать 100% если данные тянутся прямо из кэша. А вот на 4Gb все зависит от производительности памяти а не количества процов.

Я не нашел простого способа мониторить пропускную способность памяти (есть такая штука как Intel Performance Counter Monitor которая интегрируется в виндовый Performance Monitor, но ее еще скомпилировать надо intel.ly/1i0zouv).

Попробуй уменьшить размер матриц, чтобы все три одновременно влезали в L2-кэш твоего проца. Учитывая, что весь L2-кэш делится между всеми ядрами. Если проблема в памяти, то в случае с двумя процессорами скорость параллельных вычислений должна возрасти. Хотя у тебя третья матрица в 1000 экземплярах создается - это может сбить оптимизатор кэша.

Проверь (в закладке Performance в Properties процесса в Process Explorer) не использует ли матлаб другие ресурсы кроме памяти и цпу.

Date: 2014-03-18 07:48 pm (UTC)
From: [identity profile] tapka.livejournal.com
Я по теме ничего не скажу. Но циклы вообще зло. Узрите свет векторизтрованых операций!
Это у меня уже вечерний бред, на самом деле я в матлабе мало что понимаю, но R меня от циклов сильно отучил. Особенно там, где надо экономить ресурсы.

Date: 2014-03-18 09:14 pm (UTC)
From: [identity profile] green-fr.livejournal.com
Это всё понятно, у меня в примере цикл исключительно для того, чтобы время потянуть, сравнивать 19 секунд и 34, а не 0,019 и 0,034, где отличие может быть из-за того, что не вовремя сетевая плата чихнула и отвлекла процессор от моих матриц. А так всё, что векторизируется, уже давно векторизировано.

Date: 2014-03-18 08:09 pm (UTC)
From: [identity profile] oldkettle.livejournal.com
Получить удвоенное время можно из-за блокировок: мало ли для каких операций матлаб решает, что ему нужен mutex, rather than critical section. Любая операция, которая требует обращения к ОС потенциально окончится блокировкой на уровне ОС.

Date: 2014-03-18 09:15 pm (UTC)
From: [identity profile] green-fr.livejournal.com
Мне кажется, это не может быть регулярным результатом. То есть время от времени — да, причём сейчас 34 секунды, а завтра 28. А тут чётко, стабильно, всё время примерно один и тот же результат.
Тем не менее, есть какие-то методы проверки? Куда смотреть, чтобы понять, это блокировка или нет?

Date: 2014-03-19 09:25 am (UTC)
From: [identity profile] aaalex.livejournal.com
Если б были блокировки (любые), то процессор бы не жрался. Для того блокировки и используются.

Объяснением может быть то, что матлаб из рук вон плохо написан и опрашивает некий флаг в цикле вместо блокировки.

Date: 2014-03-19 05:21 pm (UTC)
From: [identity profile] green-fr.livejournal.com
Когда памяти не хватает, действительно использование CPU падает чуть ли не до нуля (а винт начинает крутиться, крутиться, крутиться...)

Date: 2014-03-18 08:54 pm (UTC)
From: [identity profile] kalvado.livejournal.com
а попробуй выставлять жестко ядра для работы копиям матлаба из интереса?

Date: 2014-03-18 09:17 pm (UTC)
From: [identity profile] green-fr.livejournal.com
А как это делать? :-)
И у тебя есть какие-то сомнения в том, что они на разных ядрах сидят? У меня есть другие примеры, которые с меньшими объёмами данных работают, и они вполне параллелятся вручную, то есть я вижу не только загрузку процессора, но и выигрыш во времени. То есть, кажется, что они на разных ядрах.

Date: 2014-03-18 09:19 pm (UTC)
From: [identity profile] kalvado.livejournal.com
Вот так: http://www.eightforums.com/tutorials/24086-processor-affinity-set-applications-windows-8-a.html
A кто на каком ядре сидит... Это, знаешь ли, такие чудеса бывают. Скорее всего оба процесса сидят на всех ядрах сразу. по крайней мере у меня матлаб во времена оны сидел на всех доступных ядрах поровну.

Date: 2014-03-18 09:22 pm (UTC)
From: [identity profile] green-fr.livejournal.com
1. У нас windows 7. Поищу, как на работу вернусь, как это делается (если ты знаешь, пиши?)
2. Точно, у меня тоже сидит как бы на всех по чуть-чуть, но мне казалось, что это бага task manager’а :-)

Date: 2014-03-18 09:26 pm (UTC)
From: [identity profile] kalvado.livejournal.com
Откуда я знаю 7? У меня ХР и 8. В ХР нашел в свое время методом научного тыка, в 8 за 40 секунд не получилось - пошел в гугл посмотрел.

И нет, не бага - точнее бага самих окошек.
и да, hyperthreading у тебя выключен? Боюсь тут оно как раз мешать будет

Date: 2014-03-18 09:37 pm (UTC)
From: [identity profile] green-fr.livejournal.com
У меня его нет (все 4 ядра настоящие) - если я правильно понял и твой вопрос, и комментарий моего IT...

Date: 2014-03-19 05:40 pm (UTC)
From: [identity profile] fima.livejournal.com
а разве hyperthreading можно отключать?

Date: 2014-03-19 06:07 pm (UTC)
From: [identity profile] kalvado.livejournal.com
вообще-то раньше было можно...
Edited Date: 2014-03-19 06:07 pm (UTC)

Date: 2014-03-20 07:24 am (UTC)
From: [identity profile] fima.livejournal.com
А, в биосе. Я думал на ходу можно.

Date: 2014-03-19 09:30 am (UTC)
From: [identity profile] aaalex.livejournal.com
process explorer

там же посмотреть, что процессор делает: в твоем коде он сидит (матлаба) или ос.

Конечно, конкретный процессор постоянно меняется. Это не должно иметь никакого влияния.

Date: 2014-03-18 09:19 pm (UTC)
From: [identity profile] muh2.livejournal.com
Так по-моему память вегда была узким местом, по сравнению с процессором. Ну по крайней мере лет 10 уже. Инструкции выполняются чуть ли не за один такт, а такт процессора много быстрее такта памяти, по крайней мере если это не кэш.

Может поможет page fault delta? Или что-нибудь еще из параметров памяти процесса. Process explorer немного лучше task manager.

Date: 2014-03-18 09:21 pm (UTC)
From: [identity profile] green-fr.livejournal.com
Я давно не занимался такими оптимизациями, годов с 1990-х, поэтому мне всегда так и казалось :-)
Соответственно, и последнюю фразу я не понимаю. Объяснишь?

Date: 2014-03-18 09:27 pm (UTC)
From: [identity profile] muh2.livejournal.com
Не. Не объясню, поскольку сам не знаю. Но пофантазировать могу. Page fault - это когда запрос памяти выскакивает за кэш и нужно из главной памяти скачать страничку. Можно заказать показывать, сколько их происходит (View/Select columns). Это может быть (или не быть) некоторой разумной (или не очень) характерстикой загрузки канала памяти.

Date: 2014-03-18 09:33 pm (UTC)
From: [identity profile] kalvado.livejournal.com
page fault - это запрос страницы с диска из pagefile

Date: 2014-03-18 09:49 pm (UTC)
From: [identity profile] muh2.livejournal.com
Упс. Ну я же говорил, что я не специалист. Но какого черта оно вообще лезет в виртуальную память в системе, в которой испольуется меньше половины физической?

Date: 2014-03-18 09:51 pm (UTC)
From: [identity profile] kalvado.livejournal.com
ну как минимум может подгружаться не весь исполняемый код, библиотеки loadoncall запросто

Date: 2014-03-19 07:02 am (UTC)

Date: 2014-03-19 08:25 am (UTC)
From: [identity profile] fima.livejournal.com
Чтобы проверить тему кэша тебе надо запустить какую-нибудь другую программу, не матлаб. которая не жрет память и кэш, но создает нагрузку на процессор, например, какой-нибудь простенький while на шелле. А затем запустить это свое сложение матриц и посмотреть сколько оно будет выполняться.

Date: 2014-03-19 05:20 pm (UTC)
From: [identity profile] green-fr.livejournal.com
Это я уже пробовал. Я запускаю другую программу на MatLab, которая что-то там своё делает с маленькими переменными (25% CPU), запускаю второй MatLab с этим скриптом (50% CPU) - 19 секунд. То есть, тормозит факт наличия двух этих "массивных" программ. Но как это подтверждает теорию. что тормозит именно память / кэш?

Date: 2014-03-19 05:39 pm (UTC)
From: [identity profile] fima.livejournal.com
Ты пробовал не это, я не говорил запускать вторую копию матлаба. Матлаб может иметь всякие локи (locks) и различные копии могут мешать друг другу. Так что ты проводил не очень чистый эксперимент. Но тебе повезло, очевидно, локи не мешают в данном случае или их там нет.
Тормозит не память, а кэш. Точнее, скорость памяти в данном случае не влияет, а размер кэша, вероятно, да.
Попробуй с матрицами меньшего размера, в 2 раза меньше, в 4 и т.п.

При работе с данными большого объема нужны другие алгоритмы. Простое разделение задачи на независимые части не поможет. Надо распараллеливать на более мелком уровне, например, распараллеливать сложение матриц. Вообще для матриц должен использоваться GPU, странно, что матлаб у тебя этого не делает (или делает?)

Date: 2014-03-20 08:26 am (UTC)
From: [identity profile] green-fr.livejournal.com
Понял, попытаюсь. Хотя и непонятно, что потом делать с полученной информацией (вот нашёл я, что при таком-то размере матрицы всё снова масштабируется - и чего теперь с этим знанием делать?)

Date: 2014-03-20 09:47 am (UTC)
From: [identity profile] fima.livejournal.com
При большем объеме данных решать задачу надо иначе.

Еще я подумал, что матлаб может как-то ограничивать собственное потребление памяти и пытаться выбрасывать матрицы или части их на диск, или пытаться паковать матрицы. Проверить тут просто, надо удвоить размер матрицы и сравнить потребление памяти.

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

Date: 2014-03-20 01:15 pm (UTC)
From: [identity profile] green-fr.livejournal.com
Это точно нет, он не пакует (умеет это делать, но надо отдельно просить это сделать), не свопит (аналогично), то есть матрица в два раза больше жрёт памяти в два раза больше.

Date: 2014-03-20 01:19 pm (UTC)
From: [identity profile] green-fr.livejournal.com
А вот про map-reduce интересно. Мне сам MathWorks что-то в этом духе предлагает, но я как-то не понимаю логики. Ну нарежу я на кусочки, на отдам я каждый кусочек отдельному процессу / процессору, что с того? Пропускная способность памяти от этого не увеличится? Как ограничивала она до этого скорость (которую можно выразить в перелопаченных мегабайтах), так и будет ограничивать, нет разве?

То есть (момент действительно для меня важный, поэтому лучше два раза его описать, чем один невнятно), если у меня скорость чтения, скажем, 100 единиц памяти в секунду, и именно эта величина ограничивает скорость моих расчётов, то, разрезав данные на 4 части, я получу 4 процесса, каждый из которых читает память со скоростью в 25 единиц в секунду, доводя память до предела скорости. Но в итоге у меня вычисления всё равно будут проходить со скоростью 100 единиц в секунду. Понимаешь? MathWorks не понял :-)

Date: 2014-03-20 01:29 pm (UTC)
From: [identity profile] fima.livejournal.com
дело же, вероятно, не в скорости доступа к памяти, а в размере кэша. надо ограничить размер данных, обрабатываемых каждым процессом в данный момент. не надо пихать всю матрицу в кэш, если за ту секунду, что процессу дана, он может только несколько строк обработать. надо добиться того, что в кэш влазят куски для всех параллельных процессов.

Date: 2014-03-20 01:39 pm (UTC)
From: [identity profile] green-fr.livejournal.com
В таком случае, тоже непонятно, зачем делать параллельные расчёты - нарезать, чтобы просто потом по кусочкам всё посчитать, и в сумме должно выйти быстрее?

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

Date: 2014-03-20 04:24 pm (UTC)
From: [identity profile] aaalex.livejournal.com
Судя по твоим результатам, если ты порежешь на кусочки (сможешь порезать у затраты на порезку/обединение результатов будут невилики), то ты уже должен выиграть даже на 1 процессоре. Плюс, откроешь дверь для паралелизации.

Date: 2014-03-20 04:50 pm (UTC)
From: [identity profile] green-fr.livejournal.com
Выиграть исключительно на том, что все (маленькие) данные будут в кэше? Нереально, либо всё переписывать на простые структуры...
А параллельные вычисления каким образом? Потому что у каждого ядра своё кэш?

Date: 2014-03-20 09:26 pm (UTC)
From: [identity profile] aaalex.livejournal.com
Именно так.
И очень часто это не реально.

Date: 2014-03-21 08:40 am (UTC)
From: [identity profile] fima.livejournal.com
Сочувствую.

Это вечная проблема систем общего назначения, они более-менее справляются с простыми задачами и очень плохо со всякими специфичными.

Date: 2014-03-20 08:27 am (UTC)
From: [identity profile] green-fr.livejournal.com
GPU MatLab теоретически умеет использовать, но не автоматически, ему нужно указывать, что посылать туда, а что нет. И там вполне себе так потеря времени на пересылку данных в и из GPU, то есть за каждым чихом не пообращаешься.

Date: 2014-03-20 09:22 am (UTC)
From: [identity profile] aaalex.livejournal.com
Еще раз про локи. Если бы они были, процессор бы не потреблялся.
Отсутствие (должной) загрузки процессора - основной признак взаимных блокировок.

Каждый матлаб ест свои 25% - блокировок нет.

И вообще, считать надо на GPU. На своих 4 процессорах ты ускоришь в лучшем случае в 4 раза.
На GPU у тебя в худьшем случае несколько сотен процессоров.

Date: 2014-03-20 09:36 am (UTC)
From: [identity profile] fima.livejournal.com
Разумно

Date: 2014-03-20 01:13 pm (UTC)
From: [identity profile] green-fr.livejournal.com
Мы просто оптимизируем сначала время разработчика (у нас нет разработчиков, разработчики - это мы, а мы плохие разработчики), а считать на GPU требует какой-то квалификации.

Date: 2014-03-20 04:18 pm (UTC)
From: [identity profile] aaalex.livejournal.com
Это правда. Писать код для GPU трудоемко получается. И поддержка/модификация потом очень тяжелая.

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

Есть общие библиотеки для питона для GPU.

Date: 2014-03-20 04:29 pm (UTC)
From: [identity profile] green-fr.livejournal.com
MathWorks примерно такое и пишет. То есть мы не обязаны писать напрямую Cudo (кажется), а есть какие-то команды типа "готовим эту переменную для GPU", "возвращаем эту переменную из области GPU". Все операции типа плюс / минус автоматически разбираются, какой тип параметра, и вычисляют там, где переменные.
Но даже на таком уровне у нас это нереально...

Profile

green_fr: (Default)
green_fr

June 2025

S M T W T F S
123 4 567
891011121314
15161718192021
22232425262728
2930     

Most Popular Tags

Style Credit

Expand Cut Tags

No cut tags
Page generated Jun. 10th, 2025 04:47 am
Powered by Dreamwidth Studios
OSZAR »