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-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
89 1011 12 1314
15 16 1718192021
22232425262728
2930     

Most Popular Tags

Style Credit

Expand Cut Tags

No cut tags
Page generated Jun. 17th, 2025 11:17 am
Powered by Dreamwidth Studios
OSZAR »