Pull to refresh
18
0
Юрий Ярош @voidnugget

Rapid Unscheduled Disassembly Expert

Send message

Собственно речь о том что если бы умели нормально их утилизировать — не нужны были бы специфические оптимизации на основе параметрических многогранников и прочего, а так для каждой SIMD инструкции или подчистки кэша надо лезть в Intrinsics интерфейс...

WPO/PGO не означает что MSVC откажется от существующих x64 ABI и начнёт их ломать в угоду утилизации регистровой памяти. К сожалению WPO/PGO не приводят к ожидаемому вами эффекту на х64'ой платформе, а на x86 просто подбирается наиболее эффективная конвенция вызовов, но существующее ABI сохраняется.


С MSDN'a:


When /LTCG is used to link modules… following optimizations are performed:
• Cross-module inlining
• Interprocedural register allocation (64-bit operating systems only)
• Custom calling convention (x86 only)
• Small TLS displacement (x86 only)
• Stack double alignment (x86 only)
• Improved memory disambiguation

Register Allocation вставляет хинты на подобие USES в MASM'е для резервирования регистровой памяти.

Это радует.
Правда на форточках пока мною замечено не было.

Про эти оптимизации во время линковки я в курсе…
Не знаю, не смотрел что на выходе получается, но вряд ли они будут ломать существующее глючное ABI.

У ICC в целом есть пару особенностей — он обычно мелочёвку оптимизирует на много лучше GCC/LLVM (20-30% компактнее и шустрее), но любые сложные вещи любит раздувать до непонятных размеров (почти в 3 раза). По этому у него свои, особенные глюки с оптимизациями… Для научных вычислений и прочего он подходит лучше чем GCC/LLVM, но любые пользовательские приложения он будет раздувать до совсем несуразных размеров.

rust использует llvm… и к форточкам это не имеет никакого отношения.
Любая C/С++ функция под форточками будет использовать существующее ABI — там нет понятия "whole program optimization" так как подобные оптимизации могут быть выполнены только во время линковки, и они не реализованы в существующих линковщиках.

Какой смысл в компиляторе, который не может полноценно использовать весь набор инструкций процессора, и требует что бы программист сам вставлял их где это нужно ?

И какое отношение это имеет к "сишичке"?

Прямое, это и есть сишное ABI, — унифицированная конвенция вызова сишных функций в форточках на x64 системах.


Какой-то компилятор генерирует код под форточки, который противоречит этому ману?

Не один существующий компилятор не генерирует код который ему следует.


… до которых так просто и не додумаешся

Не используется многопроходный GA.
Оно не сможет эффективно использовать большую часть существующих SIMD инструкций и менять последовательности команд в различных оптимизационных целях… приходится самому всегда колупаться в intrinsics'ах. Даже полигидральные плюшки не решают этот вопрос.

какие такие сишные ABI?

Например вот это нечто пожирающее стэк без острой необходимости.


оптимизации по сравнению с чем?

С официальным гайдом по оптимизации.


ну там же сам автор признал

Действительно плохой пример. Просто на практике сталкивался с подобными вещами довольно часто, чаще чем хотелось бы.


Да что уж там, один и тот же байткод будет отличатся от компилятора к компилятору ну и что?

Есть micro и macro fusion операции внутри самого блока трансляции процессора… различие в результирующем коде означает что везде они будут применяться по разному, и зависеть от солнечной радиации и положения звёзд на небе… как и производительность результирующего кода.

Есть очень много особенностей и ограничений целевых компиляторов, а также отсутствие вменяемой оптимизации в случае с Сишкой на форточках. В llvm этот вопрос решён хоть как-то, но по уровню оптимизации сишка уступает тому же rust'у. По этому от фронтенда до фронтенда один и тот же биткод (они решили отличиться) будет оптимизирован по разному.


На практике большая часть существующих оптимизаций:
• разворачивание циклов для последующего использования SIMD операций
• комбинирование макро команд для выполнение за один такт процессора (mov, test, cmp etc).
• контроль заполнения очереди комманд
• принудительная подчистка кэша
• контроль глубины ветвлений
• минимизация количества операций со стэком
• использование регистровой памяти для передачи аргументов функций
не применяются вообще, особенно в форточках, либо применяются довольно криво...


У ABI cишки слишком много консервативных и устаревших ограничений для сохранения портабельности, которые нынче не то что не нужны, а просто ставят крест на вертикальном масштабировании большинства решений.


В примерах со статьи — имеет смысл использовать SSE2/SSE4 и AVX2 операции.
Даже банальные strstr / strcmp имеют ассемблерные SIMD аналоги выполняющиеся ровно за один такт, а если правильно чистить кэш и предовращать ITLB/DTLB miss, то и по 4 штуки за такт (по 64/128 байт).


Приложения со статьи получат на выходе приблизительно одинаковый листинг ассемблерных инструкций без каких либо вменяемых оптимизаций, по этому сравнивать их не совсем корректно и целесообразно. Особенно что касается скорости системных вызовов I/O — это просто не самая удачная метрика.


Также есть специализированное File mapping API — аналог mmap Posix вызова.

С тех же, когда 30К RPS стал "высоконагрузом" PHP сайтика на конференциях по типу Highload++.

Понятие "Демона" отсутствует — используется свой планировщик с поддержкой афинности (affinity), всё в foreground'e без переключения контекста выполнения процесса. Получается так что логические ядра жёстко привязаны к процессу с DPDK. Пакеты складываются непосредственно в оперативку и большие страницы (huge pages) без участия процессора через RDMA, а целевой процесс с DPDK ловит единичное прерывание по заполнению буфера или других критериев. Доступ к сетевому интерфейсу монопольный посредством VFIO и IOMMU. Любое IPC через shmem подразумевает копирование с целевого буфера, что сильно повлияет на производительность. Идея DPDK в том что бы успевать обработать инфу в существующем буфере пока сетевуха пишет в соседний, любое копирование значительно снизит производительность. Грубо-говоря надо успевать обработать 1 клиентский запрос за 500-600 тактов процессора, желательно с использованием SIMD операций и Cache Streaming подходом. shmem используется только в качестве коммуникации для QEMU с ivshmem.


Кроме OVS есть ещё outscale/butterfly, возможно его использование в вашем случае будет более целесообразным. Так же есть порт BSD TCP/IP стэка на DPDK.


Надеюсь стало чуток понятнее.

Отличная статья, Спасибо.
Было бы неплохо написать вторую часть об RxSwift.

Опыта разработки мобильных приложений нет, но есть 5 лет опыта разработки высоконагруженных проектов на node.js, asp.net mvc.

  1. Опыт временем не меряют.
  2. Не бывает "высоконагруженных проектов" на node.js / asp.net, просто масштабируется простой процессора в разных вариациях. Без упоминания слов: "профилирование", "аффинитет" и "большие страницы" — не один проект нельзя назвать высоконагруженным.
  3. Ну да, конечно "автор ниасилил, реакт сырой, потому что… автор ниасилил". Ок, смысл в целом понятен.

Если нет опыта с нативной мобильной разработкой — нет смысла лениво надеятся что всё поедет с полпинка.
Все серьёзные конторы (SoundCloud, Facebook, AirBnB) давно пишут нативные компоненты под себя, и сами их же и поддерживают. А надеятся на посредственные поделки с гитхаба слишком наивно.


Как это весело наблюдать когда одни матерят Cordova и говорят ехать в сторону React-Native, другие матерят React-Native и призывают менять религию на Cordova… а конструктивности и конкретики в обоих случаях как-то вот совсем не наблюдается.

Вопрос "любимого дистрибутива на VPS хостинге" малость морально устарел.
Прикрутите заливку образов/менеджмент через packer.io / bosh.io / ironic — дайте людям возможность загружать что им самим будет угодно.

Читаю статью, сравниваю с документацией.
Кому-то нужно сделать соответствующие правки.

Я сейчас пишу Scala фреймворк на Scala-Native c интеграцией DPDK.
До выхода Java9 нет смысла колупаться — слишком много надо патчить в OpenJDK.
В общем Netty + DPDK потеряла актуальность из-за кучи оверхедов о которых я тогда и предположить не мог.
Сейчас вышло SPDK — есть задумки прикрутить хранилище на SPDK к PostgreSQL и ScyllaDB.

Статью оставил сугубо по историческим причинам.

Часть 1 может быть весной 2017ого, может…
А зачем что-то оставлять, если стандартный вариант использования подразумевает NUMA аффинность и запуск приложения на полностью изолированных от планировщика ядрах с пачкой больших страниц?

Там линукс нужен только для того что бы инициализировать RDMA, CBDMA и IOMMU в рамках VFIO, и всё.
В принципе, для этого можно реализовать отдельный загрузчик и полностью избавится от ядра ОС… с другой стороны вопрос менеджмента и поддержки окружения усложняется на несколько порядков.

p.s. CBDMA — common buffer DMA, есть ещё S/GDMA — Scatter/gather DMA. Разница заключается в принципе обращения и работы с памятью. Scatter/Gather может работать с фрагментированной памятью, что требует отдельных mapping регистров и снижает размер блока данных DMA транзакции SDV (Single DMA Volume). CBDMA работает с непрерывной памятью, которая называется Common buffer и является набором больших страниц, и для его работы не требуется mapping соответственно и SDV с пропускной способностью у него на много выше. S/GDMA стоит применять когда нет возможности выделить большие страницы.
Интересуют конкретные цифры.
То что там будет Overhead из-за копирования — и ежу понятно.
Профилятор — профилятору рознь. Надо понимать что есть multisample profiling, есть monitoring gap и прочие нюансы.

Было бы просто замечательно прогнать это всё в афинном окружении (numactl/taskset) на изолированных ядрах, да отрисовать flame graph'ы. Даже банального ptrace хватило бы.

Были бы цифры и графики для каждого из вариантов — было бы понятно конкретно что и сколько времени выполняется.
Слишком мало конкретики — пробуйте профилировать и получать flame graph'ы.

Information

Rating
Does not participate
Location
Киев, Киевская обл., Украина
Date of birth
Registered
Activity