Здравствуйте, CreatorCray, Вы писали:
CC>Здравствуйте, mrTwister, Вы писали:
T>>Ох, CLI прекрасен CC>Это морская свинка.
Не знаю, какая это свинка, но лучшего способа связать C++ с управляемой платформой человечество еще не придумало. Все альтернативы — это жуткое опасное дерьмище. В итоге задача, которая делается на C++\CLI за пол часа без него вполне может занять неделю. И я не преувеличиваю. Экономия времени, нервов и багов колоссальная!
лэт ми спик фром май харт
Re[7]: Производительность .Net на вычислительных задачах
LVV>>Не. CLI — это кошмар, который забыть и не использовать. T>Ох, CLI прекрасен, это офигенное преимущество dotnet'а перед всеми остальными платформами. Нет и не может быть ничего лучше для взаимодействия между управляемой и неуправляемой платформой. Жаль, что только под винду
Вот именно.
Либо мы пишем на стандартном С++ под любую платформу.
Либо мы САМИ прибиваем СЕБЯ гвоздями в кресту от Микрософт...
Хочешь быть счастливым — будь им!
Без булдырабыз!!!
Re[6]: Производительность .Net на вычислительных задачах
Здравствуйте, LaptevVV, Вы писали:
LVV>Либо мы пишем на стандартном С++ под любую платформу. LVV>Либо мы САМИ прибиваем СЕБЯ гвоздями в кресту от Микрософт...
Тема то про .Net которая под любую платформу
и солнце б утром не вставало, когда бы не было меня
Re[3]: Производительность .Net на вычислительных задачах
Здравствуйте, Sinclair, Вы писали:
KP>>Вывод тут только один — оптимизатор в Linq2q классный и наивная реализация на C++ проигрывает S>На самом деле всё наоборот — оптимизатор в linq2d наивный, написан на коленке. А С++ писали лучшие люди планеты много-много лет.
Э, там у тебя в репозитории не самый удачный С++ код, можно его ускорить в пару раз, при этом не факт, что он ещё и увеличится. Не читал код бенчмарка, но явно выделение памяти не надо делать при каждом вызове фильтра, ходить по строке не надо по одному пикселю, индекс не надо вычислять при каждом обращении к буферу. Код очень топорный.
Re[4]: Производительность .Net на вычислительных задачах
Здравствуйте, Nuzhny, Вы писали: N>Э, там у тебя в репозитории не самый удачный С++ код, можно его ускорить в пару раз, при этом не факт, что он ещё и увеличится. Не читал код бенчмарка, но явно выделение памяти не надо делать при каждом вызове фильтра,
надо. По определению — каждый вызов фильтра возвращает новый массив. Иначе будем сравнивать яблоки с бананами. N>ходить по строке не надо по одному пикселю,
Что имеется в виду? SIMD на ручных интринсиках? Как раз от этого хотелось бы уйти. N>индекс не надо вычислять при каждом обращении к буферу.
Не очень понятно, что имеется в виду. Это про вот эти вот i*width+xmax? Ну, можно, конечно, всё это в переменную выдвинуть; но я полагаю, что уж common subexpression elimination компилятор сделает не хуже меня. N>Код очень топорный.
Код максимально близок к тому образцу, который мне дал Павел Дворкин.
Но я открыт для любых улучшений. Pull request нафигачишь?
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[5]: Производительность .Net на вычислительных задачах
Здравствуйте, CreatorCray, Вы писали:
KP>>ассемблерный выхлоп вроде не изобилует векторизацией. CC>Попробуй ICC с -QxHost, там поинтереснее вывод будет
Было бы ещё неплохо научиться его использовать в гитхабовом CI конвеере. GCC я хотя бы прикрутил (хоть пока не выходит ему дополнительные флаги из проекта передать ), а по сборке vcxproj ICC инструкция есть?
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[5]: Производительность .Net на вычислительных задачах
Здравствуйте, Sinclair, Вы писали:
S>надо. По определению — каждый вызов фильтра возвращает новый массив. Иначе будем сравнивать яблоки с бананами.
Мы про этот код говорим? Там промежуточные буферы p и sq создаются и удаляются в конце функции. Никто так никогда не делает: можно один раз выделить 2 буфера и увеличивать их при необходимости, но не удалять. Поэтому в среднем выделений и освобождений памяти не будет вообще. Но это будет уже не функция, а объект и с потоками надо осторожнее.
N>>ходить по строке не надо по одному пикселю, S>Что имеется в виду? SIMD на ручных интринсиках? Как раз от этого хотелось бы уйти.
Не надо SIMD и интрисиков. Надо просто работать не побайтово, а по словам. Это вообще без оглядки на SIMD делается, а про разумное чтение из памяти и разворот цикла.
N>>индекс не надо вычислять при каждом обращении к буферу. S>Не очень понятно, что имеется в виду. Это про вот эти вот i*width+xmax? Ну, можно, конечно, всё это в переменную выдвинуть; но я полагаю, что уж common subexpression elimination компилятор сделает не хуже меня.
Надеюсь, что ты шутишь: раздуть код ненужной копипастой, которая ещё и не факт, что соптимизируется. При этом каждый раз вычислять смещение по памяти. Вообще работа с картинами принципиально по-другому делается. А именно:
— читается память единым скопом в локальные переменные (чаще всего это сразу несколько пикселей);
— производятся вычисления с этими еременными;
— результаты вычислений единым скопом записываются в память;
— читаем следующий кусок.
Извини, но тот код написан плохо.
N>>Код очень топорный. S>Код максимально близок к тому образцу, который мне дал Павел Дворкин. S>Но я открыт для любых улучшений. Pull request нафигачишь?
Можно попробовать, тестов бы ещё к нему.
Re[5]: Производительность .Net на вычислительных задачах
Здравствуйте, Sinclair, Вы писали:
S>надо. По определению — каждый вызов фильтра возвращает новый массив. Иначе будем сравнивать яблоки с бананами.
Если я правильно понял, то память под возвращаемое значение у тебя выделяется на вызывающей стороне.
SAUVOLABINARIZECPP_API int sauvolaBinarize(int height, int width, char* input, char* output, int whalf, double K)
Замечание же вот про этот код:
auto p = new int[height * width];
auto sq = new long[height * width];
...
delete[] p;
delete[] sq;
В чем проблема использовать один и тот же буфер каждый раз?
Re[6]: Производительность .Net на вычислительных задачах
Здравствуйте, Skorodum, Вы писали: S>В чем проблема использовать один и тот же буфер каждый раз?
Эмм, а как гарантировать корректную работу из нескольких потоков?
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[6]: Производительность .Net на вычислительных задачах
N>Мы про этот код говорим? Там промежуточные буферы p и sq создаются и удаляются в конце функции. Никто так никогда не делает: можно один раз выделить 2 буфера и увеличивать их при необходимости, но не удалять. Поэтому в среднем выделений и освобождений памяти не будет вообще. Но это будет уже не функция, а объект и с потоками надо осторожнее.
Ну, вот это как раз и сложно — оставаясь в рамках C API, сделать потокобезопасный код с пулом промежуточных массивов.
N>Не надо SIMD и интрисиков. Надо просто работать не побайтово, а по словам. Это вообще без оглядки на SIMD делается, а про разумное чтение из памяти и разворот цикла.
Продолжаю непонимать, увы Можно проиллюстрировать эту идею кодом?
N>Надеюсь, что ты шутишь: раздуть код ненужной копипастой, которая ещё и не факт, что соптимизируется. При этом каждый раз вычислять смещение по памяти. Вообще работа с картинами принципиально по-другому делается. А именно: N>- читается память единым скопом в локальные переменные (чаще всего это сразу несколько пикселей); N>- производятся вычисления с этими еременными; N>- результаты вычислений единым скопом записываются в память; N>- читаем следующий кусок. N>Извини, но тот код написан плохо.
Ну, меня извиняет только то, что его писал не я
N>Можно попробовать, тестов бы ещё к нему.
Хм, я попробую прикрутить к нему Linq2d.Tests.
Вообще говоря, сейчас нет гарантии, что код на С++ считает именно то, что я и думаю.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[7]: Производительность .Net на вычислительных задачах
Здравствуйте, Sinclair, Вы писали:
S>Здравствуйте, Skorodum, Вы писали: S>>В чем проблема использовать один и тот же буфер каждый раз? S>Эмм, а как гарантировать корректную работу из нескольких потоков?
thread_local тут не поможет?
Re[8]: Производительность .Net на вычислительных задачах
Здравствуйте, Skorodum, Вы писали: S>thread_local тут не поможет?
Скорее всего, thread_local спровоцирует утечку по сотне мегабайт за каждый вызов из async кода.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[9]: Производительность .Net на вычислительных задачах
Здравствуйте, Sinclair, Вы писали:
S>Здравствуйте, Skorodum, Вы писали: S>>thread_local тут не поможет? S>Скорее всего, thread_local спровоцирует утечку по сотне мегабайт за каждый вызов из async кода.
А Linq2d версия выполняет такие же аллокации или нет?
Кешируются ли эти буфера или таки выделяются новые?
Если общественность так взволнована этими аллокациями, хотя они и абсолютно легальны на мой взгляд, то можно эти два буфера так же выделять на вызывающей стороне, и тогда проблем не будет. (Хотя с точки зрения "C++" vs что-нибудь — это чистый чит.)
PS: (Вопрос к общественности) Что ложить в thread_local если каждый вызов с разными width и height?
Здравствуйте, Sinclair, Вы писали:
S>Ладно, я вроде бы нашёл, что добавление -march=skylake форсит более современную векторизацию.
К слову о общих решениях vs C++ / понятности кода: если добавил march/avx2 то хорошо бы в C++ версии так же поддерживать и платформу без AVX2, при этом в виде одного бинарника, и выбирать реализацию в рантайме — а это уже потенциально добавит костылей на N строчек кода. Я не в том плане, что это прям нужно делать, но это точно добавит шума. Я уже не говорю, о том, что msvc линкер будет читить напрополую и при малейшем нарушении ODR которое не диагностируется (зачем, ведь стандарт не обязует) — он нагенерит абсолютно невменяемый код (раз в 10х больше абсолютно бесполезных команд), который в добавок будет падать.
Здравствуйте, Mystic Artifact, Вы писали:
MA> А Linq2d версия выполняет такие же аллокации или нет?
Да, конечно. MA> Кешируются ли эти буфера или таки выделяются новые?
Нет, ничего не кэшируется. Я подозреваю, что кэширование таких буферов ухудшит производительность. Сейчас их выделение — это просто бамп указателя кучи. А кэширование будет лазить по пулу, искать свободные, в конце возвращать в пул. MA> PS: (Вопрос к общественности) Что ложить в thread_local если каждый вызов с разными width и height?
Ну, там же подразумевается что-то типа
Здравствуйте, Nuzhny, Вы писали:
N>но явно выделение памяти не надо делать при каждом вызове фильтра, ходить по строке не надо по одному пикселю, индекс не надо вычислять при каждом обращении к буферу.
1. В выделении памяти нету ничего страшного. Выделятся два больших буфера два раза. Это нормально и очень быстро
2. Хождение по одному пикселю и вычисление индекса при каждом обращении к буферу оптимизируется на этапе компиляции/линковки
У меня основная претензия к этому коду — он сильно не cache-frendly. Возможно что .net-реализация в плане работы с памятью имеет гораздо меньше промахов по кэшу.