Название: Как сделать оптимизацию Отправлено: SubaroMows от Апрель 09, 2012, 20:18 Имею дело с матрицами размером 20 x 1000000, по сути в этой матрице храню -1 или 1.(бинарные изображения).
Хотелось бы спросить, какую структуру выбрать для представления этой матрицы, чтобы работало быстрее. Пока остановился на quint8[][] Название: Re: Как сделать оптимизацию Отправлено: V1KT0P от Апрель 09, 2012, 20:19 Имею дело с матрицами размером 20 x 1000000, по сути в этой матрице храню -1 или 1.(бинарные изображения). Смотря как ты их будешь обрабатывать. Думаю лучше всего quint32 для 32 битных систем и quint64 для 64 битных.Хотелось бы спросить, какую структуру выбрать для представления этой матрицы, чтобы работало быстрее. Пока остановился на quint8[][] Название: Re: Как сделать оптимизацию Отправлено: kambala от Апрель 09, 2012, 20:26 почему бы не использовать тип bool для уменьшения потребления памяти?
Название: Re: Как сделать оптимизацию Отправлено: V1KT0P от Апрель 09, 2012, 20:30 почему бы не использовать тип bool для уменьшения потребления памяти? Если ему надо делать тяжелые операции, то вытягивание одного бита может дорого стоить.Название: Re: Как сделать оптимизацию Отправлено: Igors от Апрель 09, 2012, 20:54 почему бы не использовать тип bool для уменьшения потребления памяти? Это скользкое дело - bool может быть и 4 байта (замешан компилятор, за это получал когда переходили на Xcode)Имею дело с матрицами размером 20 x 1000000, по сути в этой матрице храню -1 или 1.(бинарные изображения). Если хранятся бинарные данные - то и хранить их надо бинарно (в виде битов). А с матрицей надо подровняться на строку. ИтогоХотелось бы спросить, какую структуру выбрать для представления этой матрицы, чтобы работало быстрее. Пока остановился на quint8[][] Код
почему бы не использовать тип bool для уменьшения потребления памяти? Если ему надо делать тяжелые операции, то вытягивание одного бита может дорого стоить.Edit: пропустил сдвиг, подправил Название: Re: Как сделать оптимизацию Отправлено: m_ax от Апрель 09, 2012, 21:49 Цитировать Код
Опять смайлик забыл поставить.. :) Название: Re: Как сделать оптимизацию Отправлено: Igors от Апрель 10, 2012, 05:21 Да, это конечно же, будет быстрый доступ к элементу) Хз что Вы хотели этим сказать - то ли действительно быстрый, то ли изображаете "сарказм знатока" :) На всякий случай поясню. Обращение к двумерному массиву примерно равно такому кодуОпять смайлик забыл поставить.. :) Код Все равно умножение, сложение потом инкремент указателя. Сравнивая этот вариант с предыдущим - да, у того на неск действий больше, но каждое из них - практически одна машинная команда. Вес операций доступа не так уж велик, поэтому брать в 8(!) раз больше памяти чтобы ускориться на пару процентов - никак не правильно. Не то это место где выжимать скорость Название: Re: Как сделать оптимизацию Отправлено: SubaroMows от Апрель 10, 2012, 10:20 Igors, спасибо. Сделаю замеры по времени работы вышей структуры и просто массива. Выложу результаты
Название: Re: Как сделать оптимизацию Отправлено: V1KT0P от Апрель 10, 2012, 12:16 Igors, спасибо. Сделаю замеры по времени работы вышей структуры и просто массива. Выложу результаты Я вот тут сделал замеры(просто перебор всех значений):
Странно что разницы между uint8 и uint32 нету. Название: Re: Как сделать оптимизацию Отправлено: Igors от Апрель 10, 2012, 12:27 Как я и говорил приведение к биту довольно таки тяжелая операция, в данном случае замедлила все в 7 раз. Самодельная структура так вообще почти в 10 раз медленее тупого массива. Интересно, только выложите проект. Меня удивляет откуда "bool to bool" 7 ???Странно что разницы между uint8 и uint32 нету. Название: Re: Как сделать оптимизацию Отправлено: V1KT0P от Апрель 10, 2012, 12:39 Как я и говорил приведение к биту довольно таки тяжелая операция, в данном случае замедлила все в 7 раз. Самодельная структура так вообще почти в 10 раз медленее тупого массива. Интересно, только выложите проект. Меня удивляет откуда "bool to bool" 7 ???Странно что разницы между uint8 и uint32 нету. Можно попробовать еще какие-то варианты =). Название: Re: Как сделать оптимизацию Отправлено: m_ax от Апрель 10, 2012, 14:29 Тест какой то неадекватный..
Согласен лишь с тем, что вариант Igors будет в любом случае самым медленным. Да и ещё, можно сравнить c std::vector<dool>. Для bool у вектора написана специализация, оптимизированная под все эти операции. Думаю с вектором получатся самые лучшие характеристики. Но это нужно проверять... На нормальных тестах) Название: Re: Как сделать оптимизацию Отправлено: V1KT0P от Апрель 10, 2012, 14:34 Тест какой то неадекватный.. Чем это неадекватный? Тестируется скорость доступа к элементу, что тут неадекватного? Название: Re: Как сделать оптимизацию Отправлено: m_ax от Апрель 10, 2012, 14:42 Цитировать Чем это неадекватный? Тестируется скорость доступа к элементу, что тут неадекватного? Во-первых нафига для этого прикручивать Qt гуй? К тому же всё равно прога работает только под виндос.. Обидно..Во-вторых: сравним вариант для binMatrix Код
с вариантом: Код
В последним варианте учитывается ещё время на уничтожение массива, в то время, как в первом варианте, при замере времени, массив ещё был жив и разрушится уже после. В-третьих.. Короче, лучше переписать это нормально, без всяких привлечений "windows.h" и вообще гуя... Да, и ещё: Лучше удалять массив так: Код
Название: Re: Как сделать оптимизацию Отправлено: Igors от Апрель 10, 2012, 15:01 Ну там массив bool и результирующая переменная bool. Не могу откомпилить на своей платформе (не имею windows.h). Ладно, вот мой тест, у меня (icc release) печатаетМожно попробовать еще какие-то варианты =). Цитировать TestMatr Я оцениваю это дело так: когда идет "только (голое) обращение" - массив быстрее в 4 раза (хотя и не в 10). Но как только вмешивается др код - зффект быстро исчезает. Напр sumNear складывает всех соседей пикселя - вроде тоже обращение, добавлены лишь проверки на границы. Тем не менее выигрыш уже только в 2 раза. А вызов скромного qrand вообще убивает в ноль.fill with qrand time = 5.97 s // заполнить случайными 0/1 fill time = 0.82 s // заполнить чередующимися 0/1 sum = 167772160, read time = 0.41 s // сумма всех элементов sumNear = 364904216, time = 3.13 s // сумма матриц 3x3 TestArray fill with qrand time = 5.88 s fill time = 0.38 s sum = 167772160, read time = 0.10 s sumNear = 364904332, time = 1.43 s Также возможно что при бОльших размерах данных (сотни мегабайт) битовые данные будут "просто быстрее" за счет того что используемый диапазон адресов меньше (дела кэша) Название: Re: Как сделать оптимизацию Отправлено: Igors от Апрель 10, 2012, 15:08 Да и ещё, можно сравнить c std::vector<dool>. Для bool у вектора написана специализация, оптимизированная под все эти операции. Думаю с вектором получатся самые лучшие характеристики. Тест я подогнал, сделайте copy/paste и вставьте std::vector<dool>. Но это нужно проверять... На нормальных тестах) Ждем-с :) Название: Re: Как сделать оптимизацию Отправлено: m_ax от Апрель 10, 2012, 15:11 Да и ещё, можно сравнить c std::vector<dool>. Для bool у вектора написана специализация, оптимизированная под все эти операции. Думаю с вектором получатся самые лучшие характеристики. Тест я подогнал, сделайте copy/paste и вставьте std::vector<dool>. Но это нужно проверять... На нормальных тестах) Ждем-с :) Сейчас пока времени нет.. Я лучше потом свой вариант теста приведу.. Название: Re: Как сделать оптимизацию Отправлено: m_ax от Апрель 10, 2012, 22:02 Написал свой тест, где сравнивал скорость чтения/записи варианта CBinMatrix, предложенного товарищем Igors с вариантом обычного массива (matrix<T, Rows, Columns>), оформленного в виде шаблона (см. исходники).
Суть теста заключалась в следующем: Создаются два массива. Первый рандомно заполняется нулями и единичками. Затем, значения элементов первого массива присваиваются соответствующим элементам второго массива. Собственно, в тесте измерялось время, которое необходимо для этой операции. Измерения были проведены для реализации CBinMatrix и шаблонной обёртки над обычным массивом (matrix<T, R, C>). Ниже его реализация: Код
Результаты Число строк и столбцов в тесте было такое: Код
В первом тесте сравнивались времена для CBinMatrix и matrix<bool, R, C> Результаты трёх запусков (release) таковы: Код CBinMatrix оказался в 2.44 раза медленнее. Второй тест: CBinMatrix и matric<char> При трёх запусках Код CBinMatrix оказался в 2.125 раза медленнее. Третий тест: CBinMatrix и matric<int> При трёх запусках Код Разница нивелируется. С std::vector<bool> пока не сравнивал.. Может завтра. Исходники теста прилагаются Название: Re: Как сделать оптимизацию Отправлено: V1KT0P от Апрель 10, 2012, 22:15 Разница нивелируется. Тут еще надо сравнивать компиляторы с разными ключами. MSVS почему-то медленнее чем GCC на дефолтных настройках. И разница между двумя тестами Igors-а не такие большие, скорее дело в том что ICC лучше оптимизирует. Я конечно пробовал собрать с помощью GCC 4.7 но программа падает О_О. При чем узнать причину нельзя, ибо в дебаг версии отрабатывает на ура.С std::vector<bool> пока не сравнивал.. Может завтра. Исходники теста прилагаются При чем там тест с подсчитыванием пикселей на int должен просто рвать любой другой, ибо CBinMatrix пока вытащит бит, пока проверит значение бита, пока перейдет по условному переходу, пока увеличит значение. В то время как для int надо всего-лишь достать значение и присвоить его. Как видно разница должна быть большая, но у меня ее почти нету. Igors замени: Код на: Код И скажи результаты, очень интересна разница с использованием ICC. Название: Re: Как сделать оптимизацию Отправлено: m_ax от Апрель 10, 2012, 22:22 Я тестил на gcc 4.4 (release) -O2
А этот мой тест на gcc 4.7 с ключом -O3 интересно что даёт? И на MSVC? Название: Re: Как сделать оптимизацию Отправлено: V1KT0P от Апрель 10, 2012, 22:35 Я тестил на gcc 4.4 (release) -O2 Ключ O3 не изменяет результаты:А этот мой тест на gcc 4.7 с ключом -O3 интересно что даёт? И на MSVC? Цитировать GCC 4.63 Щас попробу установить ICC 11 и на нем прогнать тесты.matrix<int>: time (sec) = 0.047 CBinMatrix: time (sec) = 0.156 matrix<int>: time (sec) = 0.032 CBinMatrix: time (sec) = 0.171 GCC 4.7 matrix<int>: time (sec) = 0.031 CBinMatrix: time (sec) = 0.156 matrix<int>: time (sec) = 0.047 CBinMatrix: time (sec) = 0.141 MSVS2008 matrix<int>: time (sec) = 0.063 CBinMatrix: time (sec) = 0.110 matrix<int>: time (sec) = 0.062 CBinMatrix: time (sec) = 0.125 Название: Re: Как сделать оптимизацию Отправлено: m_ax от Апрель 10, 2012, 23:04 Да, кстатии, заметил сейчас один косяк в CBinMatrix из-за которого программа падает.
Если в тесте поменять значения NUM_ROW и NUM_COL на следующие: Код то усё.. приехали.. out of range Название: Re: Как сделать оптимизацию Отправлено: V1KT0P от Апрель 10, 2012, 23:41 Щас попробу установить ICC 11 и на нем прогнать тесты. ICC 11 у меня не дал никакого прироста, наверно из-за того что проц не интел =).Цитировать ICC11 matrix<bool>: time (sec) = 0.047 CBinMatrix: time (sec) = 0.172 matrix<bool>: time (sec) = 0.062 CBinMatrix: time (sec) = 0.157 Название: Re: Как сделать оптимизацию Отправлено: m_ax от Апрель 11, 2012, 00:05 Ясненько)
Короче, пока igors не залатает свой CBinMatrix, сравнивать что-то особого смысла нет(( Название: Re: Как сделать оптимизацию Отправлено: Igors от Апрель 11, 2012, 11:28 Избегаю цитат чтобы было короче. Обращение (x, y) соответствует "столбец, строка" (как оно на экране), конечно упадет если звать "строка, столбец". Ладно, изменил на (row, col) чтобы было однообразно.
Главное - тесты показывают эффективность процессорного кэша (а совсем не эффективность кода). В аттаче немного измененный пример m_ax, где адреса выбираются подряд (rain = 0), или вперемешку (rain = 1). Теперь уже битовые данные заметно быстрее Цитировать ---- ICC rain = 0 ------- sum = 10001120 matrix<bool>: time (sec) = 0.54 sum = 10001120 CBinMatrix: time (sec) = 0.39 ---- ICC rain = 1 ------- sum = 9987800 matrix<bool>: time (sec) = 4.86 sum = 9987800 CBinMatrix: time (sec) = 1.53 ---- GCC (4.2) rain = 0 ------- sum = 10001120 matrix<bool>: time (sec) = 0.51 sum = 10001120 CBinMatrix: time (sec) = 0.53 ---- GCC (4.2) rain = 1 ------- sum = 9987800 matrix<bool>: time (sec) = 5.65 sum = 9987800 CBinMatrix: time (sec) = 2.07 Мораль: никогда не рыпайся с оптимизацией "просто так" до тех пор пока она не будет действительно узким местом :) Название: Re: Как сделать оптимизацию Отправлено: V1KT0P от Апрель 11, 2012, 11:46 Мораль: никогда не рыпайся с оптимизацией "просто так" до тех пор пока она не будет действительно узким местом :) А чего не добавил для наглядности unsigned char?Название: Re: Как сделать оптимизацию Отправлено: Igors от Апрель 11, 2012, 12:09 А чего не добавил для наглядности unsigned char? И так достаточно :). Меняя char/int/bool можно чего-то получить в разы - но только на "очень холостом" ходу, тогда оно как-то удачно ляжет в кэш. Но как только будет добавлен код обработки (пусть простейший) - эффект сразу "растворится".Если расход памяти в полтора-два раза больше - уже надо репу чесать, может ну его нафиг. А тут так резво сразу в 8 раз. Или вообще в 32, мол int быстрее :) Название: Re: Как сделать оптимизацию Отправлено: m_ax от Апрель 11, 2012, 20:20 Цитировать И так достаточно . Меняя char/int/bool можно чего-то получить в разы - но только на "очень холостом" ходу, тогда оно как-то удачно ляжет в кэш. Но как только будет добавлен код обработки (пусть простейший) - эффект сразу "растворится". Не спешите... Здесь дело не в кэше, а кое в чём другом)Немного магии меташаблонного программирования и matrix становится быстрее почти в полтора раза (при rain = 1) RAIN = 1 Код
RAIN = 0 Код
И это при том, что физически matrix содержит в 8 раз больше элементов. Так что скорость доступа и записи в CBinMatrix значительно проигрывает. Название: Re: Как сделать оптимизацию Отправлено: m_ax от Апрель 11, 2012, 21:05 Забыл сказать..
В принципе, CBinMatrix, используя подход применённый выше, тоже можно не хило ускорить) А если потом ещё использовать его в качестве специализации matrix для типа bool, то TC получит удобную шаблонную матрицу, которая в случае bool будет просто летать). Интересно, а что в итоге сам ТС наваял? Название: Re: Как сделать оптимизацию Отправлено: Igors от Апрель 12, 2012, 10:08 Немного магии меташаблонного программирования и matrix становится быстрее почти в полтора раза Во накрутили :) Если строк больше (чем столбцов) - распределяем так, иначе эдак. Результат "полтора" вполне разумен, ожидаем. Конечно, доступ к байту быстрее, извлечение бита чего-то стоит - там машинных команд в полтора раза больше.Однако достигнутые "полтора" совсем не означают "общее ускорение" - это всего лишь "ускорение доступа" или "холостой ход". Подключите нагрузку (т.е. не просто читать/писать а делать что-то полезное) - и очень быстро от того полтора останется кот наплакал. Также прикинем - а какие разумные действия будут производиться с данными которые (по своей природе) битовые? Да наверное и операции битовые, напр OR. AND. XOR двух матриц. Очевидно здесь битовые данные будут "просто в неск раз быстрее". И это при том, что физически matrix содержит в 8 раз больше элементов. Вот-вот. Если мне нужно будет 100 Mb, то Вам - 800 Mb. Такое разбазаривание ресурсов может квалифицироваться как (а) полное лоховство или (б) умышленное вредительство Название: Re: Как сделать оптимизацию Отправлено: m_ax от Апрель 12, 2012, 11:32 Цитировать Однако достигнутые "полтора" совсем не означают "общее ускорение" - это всего лишь "ускорение доступа" или "холостой ход". Подключите нагрузку (т.е. не просто читать/писать а делать что-то полезное) - и очень быстро от того полтора останется кот наплакал. Как раз таки и означает) На холостом ходу, т.е. если ТС будет использовать, при работе с матрицей, конструкции вида Код то новый вариант с matrix будет вообще в 3-4 раза быстрей. Вы же сами изменили изначальный мой вариант теста, введя RAIN, чтоб избавится от "холостого" хода... Избавились. И всё равно matrix оказывается быстрей. Но это.. Ещё не всё) Сейчас CBinMatrix - написан не самым оптимальным образом.. Можно ещё ускорить.. Но пусть этим занимается ТС) Название: Re: Как сделать оптимизацию Отправлено: Igors от Апрель 12, 2012, 11:53 Как раз таки и означает) На холостом ходу, т.е. если ТС будет использовать, при работе с матрицей, конструкции вида Не увлекайтесь - и не запутывайте начинающих :) В приведенном фрагменте скорость упрется в someFunction, и если эта ф-ция "выше травы" то эффект "быстрого доступа" упадет до нуля. А вот если нагрузка манипулирует с битами, то битовое представление ой намного быстрее :)Код то новый вариант с matrix будет вообще в 3-4 раза быстрей. Ну и давайте закругляться - все ясно, начинаем "ходить по кругу". Умолкаю Название: Re: Как сделать оптимизацию Отправлено: V1KT0P от Апрель 12, 2012, 12:02 Ну и давайте закругляться - все ясно, начинаем "ходить по кругу". Умолкаю Замеры интереснее было бы делать на реально работающем алгоритме.Название: Re: Как сделать оптимизацию Отправлено: m_ax от Апрель 12, 2012, 12:03 Цитировать А вот если нагрузка манипулирует с битами, то битовое представление ой намного быстрее Ну это и так понятно. Тут уже не нужно вытаскивать отдельный бит. С этим я и не спорю) Название: Re: Как сделать оптимизацию Отправлено: sidsukana от Апрель 12, 2012, 12:31 А использование векторных массивов не подходит?
|