Здравствуйте, vorona, Вы писали:
V>У меня результаты одинаковые только в шесть раз медленнее чем у вас V>Span: Elapsed(ms)=00:00:06.4433807 V>Unsafe: Elapsed(ms)=00:00:06.5729572
V>i7-3770S CPU @ 3.10GHz
Похоже на дебажную версию.
Re[12]: 2D-Linq и оптимизация цифровых фильтров - 3
Здравствуйте, vorona, Вы писали:
V>Здравствуйте, vdimas, Вы писали: V>>Похоже на дебажную версию.
V>Запускал dotnet run -c Release --framework netcoreapp2.1
Странно, у меня те же цифры, что и были.
А если сгенерить экзешник:
dotnet publish -r win-x64 -c release
и запустить его?
Re[3]: 2D-Linq и оптимизация цифровых фильтров - 3
Здравствуйте, Sinclair, Вы писали:
S>2. Во-вторых, есть подзадача с рекуррентным определением. Она сулит феерические впечатления при поисках возможности параллелизации. S>Пока что нахожусь на этапе мучительных поисков синтаксиса.
А мы на этапе ожидания феерических результатов.
Для затравки, кстати — в своем коде я оптимизировал вот этот кусочек. Не понравился мне тут квадратный корень, да и деления тоже.
В результате получилось нечто вообще плохо читаемое и малопонятное, но работало на 30% быстрее. Это была последняя оптимизация — после введения потоков и прочего.
К чему я это ? А просто к тому, что когда от такого алгоритма требуется максимальная скорость — это предельно далеко от задачи "напишите мне красиво и изящно".
Здравствуйте, vdimas, Вы писали:
V>Странно, у меня те же цифры, что и были. V>А если сгенерить экзешник: V>dotnet publish -r win-x64 -c release V>и запустить его?
Цифры те-же самые
Span: Elapsed(ms)=00:00:06.4222981
Unsafe: Elapsed(ms)=00:00:06.5877535
Если запускать dotnet run -c Debug --framework netcoreapp2.1
Span: Elapsed(ms)=00:00:37.8387426
Unsafe: Elapsed(ms)=00:00:10.9889554
Результат просто с массивом 14 секунд
Re[10]: 2D-Linq и оптимизация цифровых фильтров - 3
Здравствуйте, vdimas, Вы писали:
В примерах есть всё, кроме, собственно, фильтрации.
Направление мысли, в принципе, интересное, но ортогональное той задаче, которую решал я.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Pavel Dvorkin, Вы писали:
PD>А мы на этапе ожидания феерических результатов.
Пока получается выделить катастрофически мало времени — на работе нагрузку нагрузили.
Кроме того, есть риск, что вообще мега-красота не выйдет: компилятор C# работает не так, как я про него думал
А кроме Липперта мало кто пишет про то, как оно там работает "на самом деле".
PD>Для затравки, кстати — в своем коде я оптимизировал вот этот кусочек. Не понравился мне тут квадратный корень, да и деления тоже.
PD> std = sqrt((sqdiff — diff*diff/area)/(area-1)); PD> threshold = mean*(1+k*((std/128)-1)); PD> if(gray_image_ptr[j][i] <= threshold) PD> bin_image_ptr[j][i] = 0; PD> else PD> bin_image_ptr[j][i] = 255;
Ну, это можно оставить на потом. Ну, там, заменит diff/area на уже посчитанный mean; заменить деление на area-1 на area, т.к. в интересующих нас случаях эффект пренебрежимо мал (полпроцента для w=15 и меньше 0.1% для w=25).
PD>В результате получилось нечто вообще плохо читаемое и малопонятное, но работало на 30% быстрее. Это была последняя оптимизация — после введения потоков и прочего.
Ну, после Кармаковского кода меня трудно таким удивить.
PD>К чему я это ? А просто к тому, что когда от такого алгоритма требуется максимальная скорость — это предельно далеко от задачи "напишите мне красиво и изящно".
Так не может быть Хорошее инженерное решение — всегда красиво.
Ладно, отложим это до момента, когда будет что предъявить
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[5]: 2D-Linq и оптимизация цифровых фильтров - 3
Здравствуйте, Sinclair, Вы писали:
S>Ну, это можно оставить на потом. Ну, там, заменит diff/area на уже посчитанный mean; заменить деление на area-1 на area, т.к. в интересующих нас случаях эффект пренебрежимо мал (полпроцента для w=15 и меньше 0.1% для w=25).
Там существенно сложнее. Там были алгебраические преобразования, в результате которых не осталось ни sqrt, ни деления.
PD>>В результате получилось нечто вообще плохо читаемое и малопонятное, но работало на 30% быстрее. Это была последняя оптимизация — после введения потоков и прочего. S>Ну, после Кармаковского кода меня трудно таким удивить.
А это не было предназначено для того, чтобы удивить. Это было сделано с одной целью — выжать все, что можно. Кстати, это преобразование никакой компилятор сделать не сможет, потому что там фактически изменен алгоритм, хотя математически он и эквивалентен прежнему.
PD>>К чему я это ? А просто к тому, что когда от такого алгоритма требуется максимальная скорость — это предельно далеко от задачи "напишите мне красиво и изящно". S>Так не может быть Хорошее инженерное решение — всегда красиво.
Ты когда-нибудь отлаживал релизный код Visual Studio на C++ ? Это когда баг в Dеbug найти не удается (или он там почему-то не проявляется), и остается дебажить Release. Задача не для слабонервных. Исходники есть, вот только они соотносятся с машинным кодом совершенно непонятно как. Для Debug машинный код вполне соответствует тому, что на С++, а для Release — темный лес, все настолько оптимизировано, что пойди пойми. Совсем некрасиво. Зато быстро
S>Ладно, отложим это до момента, когда будет что предъявить
Здравствуйте, Sinclair, Вы писали:
V>>А самому уже не? S>Нет-нет-нет. Ваше предложение — ваш ход. Ждём-ждём.
Тебе дали аж 4 варианта индексера.
Напиши на любом из них d[x-1, y] + d[x+1, y] + d[x, y-1] + d[x, y+1] и почувствуй себя счастливым.
Тем более, что сам ты пригодный к запуску законченный код так и не дал, в отличие от меня, зато понаписал тут — у-у-у...
Re[11]: 2D-Linq и оптимизация цифровых фильтров - 3
Здравствуйте, Sinclair, Вы писали:
S>В примерах есть всё, кроме, собственно, фильтрации. S>Направление мысли, в принципе, интересное, но ортогональное той задаче, которую решал я.
Дык, я и сразу и написал про "желтушный заголовок", что ты сам решал задачу ортогональную поставленной. ))
Все твои телодвижения сосредоточились вокруг абстракции Select, но это же просто абстракция, хосподя, их можно навертеть кучей разных способов, решив таким образом исходную задачу — уйдя от оперирования в теле алгоритма конкретными типами.
Re[11]: 2D-Linq и оптимизация цифровых фильтров - 3
Здравствуйте, vorona, Вы писали:
V>У меня результаты одинаковые только в шесть раз медленнее чем у вас V>Span: Elapsed(ms)=00:00:06.4433807 V>Unsafe: Elapsed(ms)=00:00:06.5729572 V>i7-3770S CPU @ 3.10GHz
А смотрел реальную тактовую, хотя бы по диспетчеру задач?
Может, надо комп обслужить — очистить от пыли, заменить пасту на радиаторе и т.д.?
Или сам радиатор помощнее поставить?
Из твоей серии процы могут понижать частоту более чем в два раза по мере нагрева.
Re[12]: 2D-Linq и оптимизация цифровых фильтров - 3
Здравствуйте, vdimas, Вы писали:
V>Тебе дали аж 4 варианта индексера. V>Напиши на любом из них d[x-1, y] + d[x+1, y] + d[x, y-1] + d[x, y+1] и почувствуй себя счастливым.
Можно всё же в студию полное тело метода FourNeighborAverage?
Можете, если хотите, сделать его generic с where T: Struct, IArray2d<T>.
Меня интересует не "индексер" (предоставленный, потенциально, библиотекой), а полный код, который должен писать прикладной программист.
V>Тем более, что сам ты пригодный к запуску законченный код так и не дал, в отличие от меня, зато понаписал тут — у-у-у...
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[12]: 2D-Linq и оптимизация цифровых фильтров - 3
Здравствуйте, vdimas, Вы писали:
V>Все твои телодвижения сосредоточились вокруг абстракции Select, но это же просто абстракция, хосподя, их можно навертеть кучей разных способов, решив таким образом исходную задачу — уйдя от оперирования в теле алгоритма конкретными типами.
Ну, то есть примера "кучи разных способов" мы не дождёмся. Почему-то я так и думал.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[13]: 2D-Linq и оптимизация цифровых фильтров - 3
Здравствуйте, Sinclair, Вы писали:
S>Можно всё же в студию полное тело метода FourNeighborAverage? S>Можете, если хотите, сделать его generic с where T: Struct, IArray2d<T>.
Разумеется генерик, ради ж этого всё.
Без студии:
void FourNeighborAverage<T>(T array) where T : struct, IArray2d<int>
{
for(int y = 1, dy = array.DY - 1; y < dy; y++)
for(int x = 1, dx = array.DX - 1; x < dx; x++)
array[x, y] = array[x-1, y] + array[x+1, y] + array[x, y-1] + array[x, y+1];
}
Что здесь "так" в сравнении с твоим вариантом?
Здесь прикладное "знание" об алгоритме содержится в самом алгоритме, вот тут: int x = 1, DX = array.dx — 1.
В твоём же алгоритме такие "знания" необходимо каким-то образом передавать в сам абстрактный индексер.
Мой индексер получается более простым и универсальным — это просто абстракция некоторой матрицы.
Учитывая новый ref-return, можно попробовать пойти еще дальше:
[cs]
interface IArray2d<T> {
...
ref T this[int x, int y] { get; } // только геттер
}
...
unsafe void FourNeighborAverage(T array) where T : struct, IArray2d<int>
{
int dx = array.DX;
for(int y = 1, dy = array.DY - 1; y < dy; y++) {
fixed(int* current = array[1, y])
fixed(int* end = array[dx, y])
fixed(int* it1 = array[0, y])
fixed(int* it2 = array[2, y])
fixed(int* it3 = array[1, y - 1])
fixed(int* it4 = array[1, y + 1]) {
int* c = current, _1 = it1, _2 = it2, _3 = it3, _4 = it4;
while(c < end)
*c++ = *_1++ + *_2++ + *_3++ + *_4++;
}
}
}
Не, знаю, стоит ли напоминать, что в алгоритмах обработки изображений почти всегда присутствует параметр stride, который задаёт "шаг" между строками в физической памяти. Этот параметр можно загнать в конкретную реализацию IArray2d, т.е. можно побить изображение на области в том числе вертикально, т.е. распараллелить работу произвольных алгоритмов.
S>Меня интересует не "индексер" (предоставленный, потенциально, библиотекой), а полный код, который должен писать прикладной программист.
А другой программист должен будет еще этот код читать, верно?