All streams
Search
Write a publication
Pull to refresh
64
0
Павел @RPG

User

Send message
Ну отлично, а я свой алгоритм переделал — результат за 5 мс и никакой лесенки. Вот соотношение сигнал/шум в сравнении 8SED с брутом: 91.58 dB. Ошибки всего в паре пикселей. 90 децибелл это отличный результат, при сжатии изображений нормальным отклонением является где-то 50 dB.



Я вспомнил как я делал. Сначала нашёл алгоритм 8SSEDT, он в общем работал, но очень медленно. Затем нашёл статью, где предполагался более быстрый метод и реализовал его. Но математики тоже шутят и в статье оказались баги (на глаз не отличить, но благодаря вашему посту я заметил разницу). Переделаю обратно на улучшенный 8SED.

На очереди попробовать алгоритм с антиалиасингом.
Так как мы храним дельты по осям: dx и dy, а сравнивать нам нужно дистанцию (и записывать минимальную), то нам придется каждый раз вычислять квадрат расстояния dx*dx+dy*dy, чтобы мы могли его сравнить. Авторы решили сэкономить на этом.

Это на самом деле я и есть автор этого бреда. С математической точки зрения это выглядит как неоптимизированный код, но на самом деле эта функция написана специально под компилятор (ветвления выкидываются путём подстановки констант) — то есть в финальном скомпилированном варианте не будет практически ни единого ветвления. И доп. переменную с квадратом расстояния тоже делал я:) Поскольку мне надо было добиться скорости алгоритма менее 1 секунды для изображения 4к, получился вот такой монстр. Сделать лучше при той же производительности не получилось (этот код быстрее где-то на 15%).

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

P.S. То что сейчас в гите — сильно устарело.
Для сравнения, картинка, которую я получил методом брутфорса. Прямолинейный простейший алгоритм. И тут тоже лесенка:



Так что это либо повод задуматься, либо я где-то ошибся… Но рискну предположить, что ваш метод на GPU ещё как-то учитывает антиалиасинг и сглаживает переходы в ущерб точности, но в пользу красоты результата.

Далее по производительности (Core 2 quad):
брутфорс — 462 сек
8SSEDT — 0.046 сек (46 мс)

Как видно, практически также быстро как GPU. У меня правда он ещё два прохода считает (знаковая карта расстояний), эти два прохода можно запустить на двух процессорах без особых проблем. SIMD там прикрутить тоже можно, но лениво.
У меня алгоритм 8SSEDT, только что выяснил. Дело давно было, а ступеньки и прочее — ошибки реализации. Я когда искал хоть какой-то алгоритм, было днём с огнём не сыскать. Сейчас если чуть-чуть копнуть — оказывается существует десяток методов.

Вот оригинальная реализация: www.codersnotes.com/algorithms/signed-distance-fields (ступеньки прилагаются).

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



Принцип такой же (окно 3х3), но возможно алгоритм модифицированный. Ещё на картинки видны какие-то артефакты на удалении, но это похоже на ошибку в реализации.
Более того, нормальные компиляторы уже давно умеют выдавать предупреждения практически по всем описанным в статье нюансам, и это я даже не говорю про компилятор-анализатор clang. Оба компилятора доступны студентам безо всяких унижений.

Но проще сказать чем сделать — кто из студентов смотрит на предупреждения компилятора, сдавая зачёт в последний день? И кто сказал, что такие студенты начнут пользоваться анализаторами, стыдливо показывая пустую зачётку?:)
Хм, а с каких пор научились удалять данные из оперативной памяти методом Гутманна, можно поподробнее?

Из заголовка статьи я так понял, что смысл всего этого — ленивое освобождение памяти, с чем пул справляется превосходно, более того, объектная система GTK вообще позволяет практически не освобождать память за счёт выстраивания иерархии указателей. Когда мы говорим о защите памяти, то как правило я подразумеваю что-то вроде ASLR, NX-bit, PaX, но никак не Гутманна.

Скорее всего, другие читатели вас тоже не поймут, так как статья начинается со слов «чтобы не пичкать код вызовами free», а далее начинается отдельная история про защиту памяти и надёжность.

Лично я выбрал для себя Linux-like стиль программирования с активным использованием goto (да-да).
Тогда смысл песочницы я вообще не понял, хотя пролистал статью несколько раз. В принципе, я могу и при помощи malloc выделить кусок памяти размером 64 килобайт и потом сделать для него free в конце программы (кстати GNU не считает за ошибку, если free вообще не делать для долгоживущих объектов), а что станет с песочницей, когда 64 КБ будет мало и нужно будет сделать realloc?
Если ли принципиальное отличие от APR Pool?
пока пассажир не поднялся на высоту 10 тысяч километров

Я бы такой авиакомпанией никогда не полетел несмотря на все меры безопасности:)
Вообще когда совсем одолевает лень при написании тестов:

* пишем тесты с выводом в stdout, вроде такого:

puts("Testing feature 1...");
printf("%d\n", result);

* запускаем наше хозяйство с выводом в простой текстовый файл, и сохраняем его куда-нибудь в укромное место как «эталон»
* повторный запуск — сравниваем результат с эталонным файлом чем-то вроде diff
* обновляем тесты — обновляем эталон

А когда не лень делают так: github.com/danmar/cppcheck/blob/master/test/testtokenize.cpp
(__COUNT__ мой компилятор не поддерживает).

А __LINE__?
Просто потому что пост-инкремент ведёт себя в понимании программистов «правильно», но если поменять его на пре-инкремент, большинство удивляется результату. То что компилятор генерирует правильный код ещё не означает, что это не UB. Хотя конечно компилятор мог бы кинуть хотя бы предупреждение, gcc молчит как партизан, зато clang выдаёт:

test.c:4:29: warning: unsequenced modification and access to 'i' [-Wunsequenced]
        for(i = 0; i < 10; a[i] = i++);

Если вас и компилятор не убедит, то мне и подавно никто не поверит.
Это кстати есть в Frequently Reported Bugs GCC. Если кратко — всё, что происходит между точками следования, может происходить в произвольном порядке на усмотрение компилятора. Просто компиляторы научились предугадывать такие финты программистов, поэтому если отбросить экзотику, остаются только gcc, clang и VS, которые старательно избегают подобного рода багов в программах — в противном случае общественность обвинит компилятор в том, что «нормальные» программы в нём не собираются.
Не уверен, мне вообще хотелось бы увидеть адекватные комментарии по этому вопросу вместо совета использовать RtlSecureZeroMemory.
V677 Custom declaration of a standard 'BYTE' type.

В каком таком стандарте описан тип BYTE?

RtlSecureZeroMemory() function should be used

Как бальзам на душу разработчикам кроссплатформенной библиотеки.

Не проще ли так?
static inline void *memset_safe(void *s, int c, size_t n) {
  void *ret = memset(s, 0, n);
  *(volatile char*)s= *(volatile char*)s;
  return ret;
}
Так и речь не о том, что анализатор взял и выдал: «у вас CVE-2014-XXXX в строке номер 150», а о том, насколько реально помогли анализаторы при ловле этих самых CVE. Касательно аудита безопасности успешных примеров пока маловато, чтобы говорить о том, что анализатор помогает в обнаружении уязвимостей. Ибо уязвимость — это не просто ошибка, а ошибка, которую (пусть даже в теории) можно проэксплуатировать, но анализатор не может подсказать, как именно, он не знает особенности этой программы и не знает, что в этой строке может оказаться пароль или внешние данные. Именно поэтому мы редко видим новости «Анализатор ХХХ помог найти уязвимость YYY», хотя уязвимости в СПО отстреливают ежедневно.
Доля уязвимостей, найденных статическими анализаторами ничтожно мала по сравнению с тем, на что натыкаются эксперты при анализе кода. Стоило обратить внимание людей на шеллшок, как там нашли сразу по меньшей мере 6 (!) уязвимостей и наложили около 30 патчей.

Из последних на моей памяти реально присвоенных CVE, что нашли анализаторы — уязвимость в Х.org, которую нашёл cppcheck. Это капля в море в пересчёте на адское количество ложных срабатываний.

В итоге так и живём — вся суть отечественного аудита кода заключается в гуглении CVE-шек из OpenSource проектов.
Там не так остро стоит проблема зависимостей. Даже опенсорсный софт для винды пакуется со всеми библиотеками в то время как в линуксе он честно тянет зависимости.

В некоторых случаях это даже лучше. В Linux наоборот идут в сторону контейнеров для софта.
2014 год. В винде появился пакетный менеджер. Появился адекватный шелл. Чем ещё удивит?

Information

Rating
Does not participate
Location
Москва, Москва и Московская обл., Россия
Date of birth
Registered
Activity