← All posts tagged С++

SannySanoff

Самая привередливая из всех dependencies для текущего проекта — это плюсовая либа GRPC, с ней постоянно что-то не так, она резко выделяется из остального зоопарка. Из гита скрипт ее сборки идет с "treat warnings как errors", и это означает, что изначально есть настрой на победу — она наверняка не будет работать с твоим компилятором или дистром. Приходится патчить отключать эту опцию, варнинги потом норм, совершенно безобидные, все собирается, работает.

Из последнего: текущий релиз (1.23.0) не собирается на убунте 19.10, потому что переопределяет функцию из системных инклудов, в ранних убунтах, арчах итд этого не было.

Поэтому фиксировать в билд скриптах версию в GRPC и подобных СТРАННО написанных пакетов — бессмысленно, потому что через год все равно не соберется.

И самое жеж удивительно, все эти глюки со сборкой — НЕ оттого, что там, в GRPC, они выжимают последний миллиметр оптимизации ради, задействуя недокументированные или нестабильные фичи — это бы я понял. В совершенно тупых местах нежданчики. То ли горе от ума, то ли еще какой-то фактор.

SannySanoff

По поводу #2932127 2 месяца спустя:

половину функций не вызвать в evaluation окошке вернулся обратно к gdb, оказывается можно компилить шлангом, отлаживать гдб, не знаю чего я тупил, теперь евалюейтится все

минус скорость компиляцииzapcc !!! плюс скорость компиляции!

минус удобные немутабельные структуры
написал себе протобуф кодеген в Ц++ в функциональные структуры для немутабельного использоварния с шаред пойнтерами.

минус лаконичность
Дефайны инлайны темплейты auto c++17 — уже норм.

Человек привыкает ко всему.

(Зато теперь у меня запуск в отладке qt тестового клиента занимает 12 секунд — в отладчик грузятся 100 шлиб, в 1 поток, можно отдохнуть перед тем как прога начнет работать)

SannySanoff

закончилось тем, что я переписал под себя cf (composable futures), точнее, я их выкинул и написал свое future/promise/when_all и все такое. Почему? Потому что те что были, как мне показалось, глючили в одном случае. Пока переписывал, оказалось мой баг был в моем коде, но дописал все равно.

Работает в несколько раз быстрее: копирует меньше, аллокаций делает меньше, и, стало быть, занимает меньшую долю общей нагрузки на мультицпу, кучу итп, я доволен. То шо было раньше, для моих нужд overengineered.

SannySanoff

Программирование дата процессинга на современных плюсах с STL на быстрой тачке подобно программированию на жабе на средней тачке,

минус удобство отладки (аццкие шаблоны не посмотреть нормально значения в окошке, половину функций не вызвать в evaluation окошке)

минус скорость компиляции

минус удобные немутабельные структуры (ибо аллок в жабе != аллок в плюсах) отсюда минус скорость выполнения потому что выходит больше copy by value (маленьких данных, в основном куски parse tree, не больших) чем хотелось бы (sic!)

минус лаконичность

ну а так уже почти привык.

SannySanoff

Написал немножечко на плюсцах native функций для kdb+, каких-то жалких 45кб сорцов, уже насобиралось 41килобайт кода:

11 .text 0000a250 0000000000001680 0000000000001680 00001680 2**4

Правда я там злоупотребляю жеж темплейтами для специализации по разным типам 8-)

Заглянул внутрь, а там — мама мия! Как далеко мы(они) ушли от z80 и от x86!

2199: 49 8d b2 c0 00 00 00 lea 0xc0(%r10),%rsi
21a0: 41 83 c0 04 add $0x4,%r8d
21a4: 62 11 7e 48 6f 44 17 vmovdqu32 0x80(%r15,%r10,1),%zmm8
21ab: 02
21ac: 62 f3 7d 48 3b c2 01 vextracti32x8 $0x1,%zmm0,%ymm2
21b3: 62 11 7e 48 6f 64 17 vmovdqu32 0xc0(%r15,%r10,1),%zmm12
21ba: 03
21bb: 62 f3 7d 48 3b e6 01 vextracti32x8 $0x1,%zmm4,%ymm6
21c2: 62 53 7d 48 3b c2 01 vextracti32x8 $0x1,%zmm8,%ymm10
21c9: 62 f2 7d 48 25 c8 vpmovsxdq %ymm0,%zmm1
21cf: 62 53 7d 48 3b e6 01 vextracti32x8 $0x1,%zmm12,%ymm14
21d6: 62 f2 7d 48 25 da vpmovsxdq %ymm2,%zmm3
21dc: 62 f2 7d 48 25 ec vpmovsxdq %ymm4,%zmm5
21e2: 62 f2 7d 48 25 fe vpmovsxdq %ymm6,%zmm7
21e8: 62 b1 fd 48 7f 0c 52 vmovdqa64 %zmm1,(%rdx,%r10,2)
21ef: 62 52 7d 48 25 c8 vpmovsxdq %ymm8,%zmm9
21f5: 62 52 7d 48 25 da vpmovsxdq %ymm10,%zmm11
21fb: 62 b1 fd 48 7f 5c 52 vmovdqa64 %zmm3,0x40(%rdx,%r10,2)
2202: 01
2203: 62 52 7d 48 25 ec vpmovsxdq %ymm12,%zmm13
2209: 62 52 7d 48 25 fe vpmovsxdq %ymm14,%zmm15
220f: 49 81 c2 00 01 00 00 add $0x100,%r10
2216: 45 39 c3 cmp %r8d,%r11d
2219: 62 f1 fd 48 7f 2c 7a vmovdqa64 %zmm5,(%rdx,%rdi,2)
2220: 62 f1 fd 48 7f 7c 7a vmovdqa64 %zmm7,0x40(%rdx,%rdi,2)
2227: 01
2228: 62 71 fd 48 7f 0c 42 vmovdqa64 %zmm9,(%rdx,%rax,2)
222f: 62 71 fd 48 7f 5c 42 vmovdqa64 %zmm11,0x40(%rdx,%rax,2)
2236: 01
2237: 62 71 fd 48 7f 2c 72 vmovdqa64 %zmm13,(%rdx,%rsi,2)
223e: 62 71 fd 48 7f 7c 72 vmovdqa64 %zmm15,0x40(%rdx,%rsi,2)

И еще loop unrolling там есть, типа если на входе от нуля до 8, то прыгается прямо на нужное место, в котором развернут частный случай, а иначе оно кусками по 8 элементов фигачит. Это так потому что AVX512.

Современная сишечка меня пугает и завораживает одновременно.

SannySanoff

Вот у меня есть функция, параметризуемая каким-то n, в ней есть цикл по n, и массив внутре есть.
я хочу наделать шаблонов(templates), для n от единицы до пяти, чтобы во время template instantiation это n становилось compile-time константой, а для остальных n пусть будет generic функция, в которой n будет переменной. А функцию я буду вызывать из switch/case соответственно разные специализации шаблона.

С шаблонами в принципе я уже тут кой-чо накидал, но все примеры нахожу только такие, что для специализаций по конкретному числу (от 1 до 5) тут можно написать везде свою реализацию, а для неспециализированной версии (остальных N) еще одну реализацию. Для меня же главное, чтобы КОД ФУНКЦИИ РЕЮЗАЛСЯ для специализированной и неспециализированной версии, то есть в одном случае n будет параметром шаблона, в другом параметром функции.

Может кто-то решал такую задачу, или есть идеи? Понимаю, что прямых путей нет, и еще, что все можно сделать препроцессором, но все-таки неохота препроцессором.

SannySanoff

Откровение: то, что тормозит на чтении 100000 мелких файлов на ext4 даже когда они все в буферах закешированы, тормозит так же точно и на рамдиске, если эти файлы туда засунуть. Директории в процессе не сканируются еслишо, прямо опен делается внутре.

cpu sys 12%, user 5% например (одно ядро)

С какого это бодуна?

SannySanoff

*programming

Одолел на гейбуке FFMpeg, OpenGL, OpenCL, OpenCV, SDL и VideoToolbox hardware decoding, писал на плюсах.

Короче, FFMpeg через RTSP получает кусочек фрейма с IP камеры.
Затем это скармливается в VideoToolbox. Он мне в GPU дает буфер.
Потом это я из этого делаю OpenGL текстуру, из нее делаю OpenCL mem_obj.
Потом таки GPU->GPU копирую в OpenCV UMat (GPU-based матрицу) для алгоритмов всяческих.
Потом делаю алгоритмы
Потом стало быть беру из SDL тот SDL_Surface который рисую, и маплю его на другой mem_obj
Потом копирую из OpenCV матрицы (GPU->GPU) в етот surface/texture.
И потом тут же его рисую снова через SDL не вылазя в host RAM. Наверняка, если потрахаться с форматами текстуры, можно и не копировать, миллисекунду-другую выигрываешь.

Короче, выходит, что все быстро декодируется, весь процессинг и отображение происходит не покидая GPU, с дыркой куда вставить OpenCV/OpenCL вызовы для графических алгоритмов.

Все это дело занимает 7% CPU и чуток GPU на 25 кадрах Full HD, около 7 мсек на кадр выходит (в основном декодирование 5 мсек). У меня на гейбуке устроен Intel IRIS 6100, это подобие GPU.

Когда я стал затем прикручивать OpenCV процессинг на тамошних матрицах, оно занимает по 4-5 мсек на проход одной матрицы кернелом, просто чтобы хотя бы сложить 2 такие матрицы. Потому что Full HD и интел. А целиком весь мой задуманный процессинг получается 100 Мсек на кадр, потому что куча матричных операций. Это неинтересно. Полез смотреть как оно устроено, увидел там как выглядит голый OpenCL kernel (и не один), чей исходник они препроцессором допиливают под конкретные типы прежде чем запускать.

Решил, а чем мы хуже. Взял переписал весь свой алгоритм на OpenCL на тамошней сишечке, OpenCV предоставляет простой API. 18 миллисекунд на кадр, братие! Из говенного интела! Туда еще столько влезет!

Короче, прикольно-то как! Чувство глубокого удовлетворения.

SannySanoff

Мне не нравятся итераторы в C++ STL.
В чем их фишка? Для чего они внесены вообще? Компилятся ли они достаточно эффективно в случае, например, обычного vector, достаточно ли годный выходит код после всех этих инлайнов и темплейтов?

Привык к коллекциям жабы, теперь морщусь.