- Бенчмарки Apple M1 в реальной разработке
- Тестовое окружение
- Java Renaissance
- Java SciMark 2.0 (NIST)
- Java DaCapo
- Python PyPerformance
- Go (golang.org/x/бенчмарки)
- Go (golang-benchmarks)
- SQLite Bench
- Redis
- JavaScript Web Tooling Benchmark (v8)
- Apple M1 хорош, но насколько он хорош в трассировке лучей?
- Подробнее о ChameleonRT
- Трассировка лучей на ГП через Metal
- Быстрая трассировка лучей на ЦП с библиотеками Intel
- Бенчмарки
Бенчмарки Apple M1 в реальной разработке
Я очень впечатлён результатами тестов Apple M1. Это действительно быстрый и мощный чип в важных повседневных задачах, таких как просмотр веб-страниц, работа с приложениями x86 и инструментами разработчика. Да, экосистема ещё не развита, и это может занять некоторое время, но эта работа стоит того, с учётом феноменальной производительности M1.
М1 действительно быстрый, и многие бенчмарки доказали его эффективность. Однако мне было любопытно посмотреть на производительность языков программирования. Поэтому я решил протестировать чип в самых популярных рабочих нагрузках в разработке.
Следует иметь в виду, что некоторые наборы тестов нагружают память, другие зависят от производительности CPU, а в некоторых задачах нет преимущества от многоядерной обработки из-за накладных расходов или сложности использования многопоточности. Это означает, что M1 может показать лучший результат, чем десктопный Ryzen даже с меньшим количеством ядер. Самое главное, что я сосредоточился на тестах реальных задач разработки, а не на синтетических тестах продакшна.
Исходные данные бенчмарка здесь.
Примечание: количество ядер 3900X бесполезно для тестов, которые не показывают реальную производительность в продакшне. Но сами разработчики большую часть времени работают на ноутбуках, настольных компьютерах и т. д., поэтому такие тесты имеют смысл. Конечно, в продакшне Ryzen 3900X будет работать намного лучше, чем M1 и Intel, в основном, за счёт распараллеливания.
Тестовое окружение
Java Renaissance
Чем меньше, тем лучше
Renaissance — это современный, открытый и диверсифицированный набор тестов для JVM, направленный на тестирование JIT-компиляторов, сборщиков мусора, профайлеров, анализаторов и других инструментов.
Поскольку JVM требует большого объёма памяти, а память является одним из главных узких мест для любых Java-приложений, производительность Apple M1 ошеломляет по сравнению с Ryzen 3900X.
Java SciMark 2.0 (NIST)
Чем больше, тем лучше
SciMark 2.0 — это Java-бенчмарк для научных и численных вычислений. Он замеряет производительность нескольких вычислительных ядер и сообщает сводную оценку в приблизительных мегафлопсах (миллионы операций с плавающей запятой в секунду).
Java DaCapo
Чем меньше, тем лучше
Тестовый набор DaCapo состоит из набора опенсорсных приложений реального мира с нетривиальной загрузкой памяти.
Python PyPerformance
Чем меньше, тем лучше
Проект PyPerformance должен служить авторитетным источником бенчмарков для всех реализаций языка Python. Основное внимание уделяется реальным, а не синтетическим бенчмаркам. Где возможно, используются полные приложения.
Go (golang.org/x/бенчмарки)
Чем меньше, тем лучше
Обратите внимание, что в этом бенчмарке Go использует все ядра.
Go (golang-benchmarks)
(Единицы измерения: наносекунд на операцию, чем меньше, тем лучше)
Apple M1 (Mac Mini) | Apple M1 (MacBook Air) | Ryzen 3900X | Intel i7-9750H | |
---|---|---|---|---|
BenchmarkBase64decode-24 | 68,65 | 69,77 | 137,1 | 103 |
BenchmarkBase64regex-24 | 12001 | 12001 | 32803 | 18255 |
BenchmarkNumberRegEx-24 | 7759 | 7931 | 23379 | 12206 |
BenchmarkFulltextRegEx-24 | 6388 | 6388 | 18627 | 10014 |
BenchmarkNumberParse-24 | 48,69 | 50,19 | 66,83 | 58 |
BenchmarkFulltextParse-24 | 726,3 | 726,3 | 933,2 | 839 |
BenchmarkConcatString-24 | 21949 | 22810 | 65498 | 43343 |
BenchmarkConcatBuffer-24 | 4,338 | 4,648 | 6,258 | 6,24 |
BenchmarkConcatBuilder-24 | 2,37 | 3,1 | 2,934 | 3,02 |
BenchmarkContains-24 | 5,007 | 5,204 | 7,467 | 7,94 |
BenchmarkContainsNot-24 | 6,322 | 6,322 | 7,693 | 8,9 |
BenchmarkContainsBytes-24 | 5,33 | 5,511 | 7,5 | 8,49 |
BenchmarkContainsBytesNot-24 | 6,57 | 6,773 | 9,188 | 10,3 |
BenchmarkCompileMatch-24 | 70,66 | 75,09 | 110,1 | 83 |
BenchmarkCompileMatchNot-24 | 31,65 | 32,08 | 62,42 | 42,1 |
BenchmarkMatch-24 | 800,2 | 804,6 | 2376 | 1313 |
BenchmarkMatchNot-24 | 758,1 | 779,3 | 2311 | 1262 |
BenchmarkForMap-24 | 18,89 | 18,92 | 20,37 | 20,6 |
BenchmarkRangeMap-24 | 47,66 | 48,59 | 53,25 | 56,7 |
BenchmarkRangeSlice-24 | 3,446 | 3,47 | 2,022 | 3,4 |
BenchmarkRangeSliceKey-24 | 4,072 | 4,121 | 2,906 | 3,15 |
BenchmarkAdler32-24 | 699 | 719,4 | 644,4 | 700 |
BenchmarkBlake2b256-24 | 2340 | 2415 | 2026 | 1932 |
BenchmarkBlake2b512-24 | 2343 | 2400 | 1985 | 1945 |
BenchmarkBlake3256-24 | 5753 | 5854 | 2489 | 2634 |
BenchmarkMMH3-24 | 374,3 | 383,2 | 294 | 377 |
BenchmarkCRC32-24 | 255,5 | 260,4 | 152,9 | 122 |
BenchmarkFnv128-24 | 4468 | 4502 | 5540 | 4210 |
BenchmarkMD5-24 | 3193 | 3211 | 2464 | 2534 |
BenchmarkSHA1-24 | 900,4 | 910,9 | 1898 | 1961 |
BenchmarkSHA256-24 | 913,5 | 927,6 | 4016 | 4525 |
BenchmarkSHA512-24 | 6999 | 7033 | 2883 | 3249 |
BenchmarkSHA3256-24 | 4213 | 4231 | 5957 | 5878 |
BenchmarkSHA3512-24 | 7329 | 7429 | 10233 | 10394 |
BenchmarkWhirlpool-24 | 32042 | 32624 | 35714 | 39205 |
BenchmarkMapStringKeys-24 | 68,14 | 70,66 | 87,62 | 100 |
BenchmarkMapIntKeys-24 | 43,6 | 48,49 | 42,51 | 60 |
BenchmarkJsonMarshal-24 | 1240 | 1261 | 2258 | 1720 |
BenchmarkJsonUnmarshal-24 | 4969 | 5102 | 9597 | 6484 |
BenchmarkMathInt8-24 | 0,3128 | 0,3235 | 0,2298 | 0,24 |
BenchmarkMathInt32-24 | 0,3145 | 0,3166 | 0,2324 | 0,239 |
BenchmarkMathInt64-24 | 0,3131 | 0,3158 | 0,2367 | 0,237 |
BenchmarkMathAtomicInt32-24 | 6,9 | 6,965 | 4,02 | 4,33 |
BenchmarkMathAtomicInt64-24 | 6,898 | 7,051 | 4,044 | 4,27 |
BenchmarkMathMutexInt-24 | 13,51 | 13,63 | 8,118 | 12,1 |
BenchmarkMathFloat32-24 | 0,3142 | 0,3142 | 0,3142 | 0,241 |
BenchmarkMathFloat64-24 | 0,313 | 0,313 | 0,313 | 0,239 |
BenchmarkParseBool-24 | 1,427 | 1,43 | 0,2252 | 0,308 |
BenchmarkParseInt-24 | 10,97 | 11,15 | 11,84 | 13,5 |
BenchmarkParseFloat-24 | 64,52 | 65,74 | 90,89 | 87 |
BenchmarkMathRand-24 | 13,55 | 13,55 | 17,27 | 21,5 |
BenchmarkCryptoRand-24 | 106,6 | 112 | 1311 | 145 |
BenchmarkCryptoRandString-24 | 107,6 | 110,7 | 222 | 138 |
BenchmarkMatchString-24 | 4957 | 5148 | 13869 | 7616 |
BenchmarkMatchStringCompiled-24 | 475,5 | 496,2 | 499,2 | 464 |
BenchmarkMatchStringGolibs-24 | 479,3 | 496,3 | 491,3 | 480 |
SQLite Bench
Чем меньше, тем лучше
Redis
Чем больше, тем лучше
JavaScript Web Tooling Benchmark (v8)
Чем больше, тем лучше
V8 Web Tooling Benchmark — это набор тестов для измерения рабочих нагрузок JavaScript в веб-разработке, таких как основные рабочие нагрузки в популярных инструментах вроде Babel и TypeScript. Цель в том, чтобы измерить конкретно производительность JavaScript (на которую влияет движок JavaScript), а не ввод-вывод или другие несвязанные аспекты.
Подробное описание тестов в этом наборе см. здесь.
Источник
Apple M1 хорош, но насколько он хорош в трассировке лучей?
Чип Apple M1, установленный в новых MacBook Air, MacBook Pro и Mac Mini, уже стал предметом множества обсуждений, статей о бенчмарках и публикаций в блогах. Скорость и производительность его действительно впечатляют, особенно касаемо производительности на ватт.
Но конкретно сейчас мы остановимся подробнее на трассировке лучей — в частности, на трассировке лучей через API Metal, анонсированный на WWDC-2020.
Для тестов в данной статье использовались Mac Mini и интерактивный трассировщик пути ChameleonRT, а сравнение проводилось с DirectX, Vulkan, OptiX и Embree.
Подробнее о ChameleonRT
ChameleonRT — интерактивный трассировщик пути с открытым исходным кодом, созданный для изучения различных API трассировки лучей. Он предоставляет бэкэнд для таких API, как DirectX Ray Tracing, Vulkan KHR Ray Tracing и OptiX 7, а теперь и Metal. Также он поддерживает бэкэнд Embree для быстрой многопоточной и ускоренной с помощью SIMD трассировки лучей на ЦП через Embree, ISPC и TBB. Код рендеринга в каждом случае практически идентичен. На выходе получаются пиксельные данные с возможными небольшими различиями, связанными с различиями в библиотеках трассировки лучей и языках шейдеров.
ChameleonRT отличается от популярных приложений для тестирования трассировки лучей, таких как CineBench, LuxMark и Blender Benchmark. Он представляет собой минимально необходимый для тестирования интерактивный трассировщик путей. CineBench, LuxMark и Blender Benchmark отлично подходят для получения полного представления о том, какую производительность ожидать от производственного рендерера. Однако в производственном рендерере происходит гораздо больше, чем просто трассировка лучей: в нем заложена поддержка сложной геометрии, материалов и эффектов, используемых в фильмах, а масштабные кодовые базы сложно переносятся на новую архитектуру или API.
ChameleonRT — их полная противоположность, поддерживающая только один тип геометрии — треугольные мэши — и один тип материала – Disney BRDF. Остальной код написан в целом аналогично другим бенчмаркам для достижения производительной интерактивной трассировки пути, но в то же время так, чтобы его было довольно просто читать. Например, рендереры здесь используют итеративную трассировку лучей вместо рекурсивной, а также только простую стратегию сэмплинга, и не поддерживают эффекты cutout. Использование итеративной трассировки лучей полезно как для ЦП, так и для ГП, хотя для последнего особенно важно — ведь нагрузки при вызове программной рекурсивной трассировки лучей могут существенно повлиять на производительность. Точно так же игнорирование cutout эффектов позволяет рендерерам ГП пропускать использование hit-шейдеров. Они будут вызваны уже во время обхода BVH после нахождения пересечения с треугольником. Аппаратное ускорение обхода BVH приводит к возникновению большого количества возвратов между фиксированной функцией обхода BVH и ядрами для запуска hit-шейдера, что ограничивает производительность оборудования.
Что такое трассировщик пути? Трассировка пути — это метод рендеринга фотореалистичных изображений путем симуляции переноса света в сцене. Это метод Монте-Карло, случайным образом выбирающий пути прохождения света, попадающего в камеру, отражаясь от объектов в сцене. Он реализуется посредством отслеживания пути в направлении от камеры обратно через всю сцену. Для получения изображения без шума необходимо выполнить сэмплинг большого количества световых путей. Трассировка пути не ограничивается применением только в фотореалистичный изображениях. Она также широко используется в кинорендерерах, таких как Renderman от Pixar, Hyperion от Disney, Arnold от Autodesk и Manuka от Weta.
Трассировка лучей на ГП через Metal
Трассировка лучей в новом Metal API похожа на встроенную трассировку лучей в DirectX или Vulkan. Чтобы узнать подробнее, что представляет из себя Metal, можно посмотреть видео с WWDC 2020 и ознакомиться с этим кодом. Встроенная поддержка трассировки лучей позволяет приложениям выполнять вызовы трассировки лучей в шейдерах на любом этапе — например, в шейдерах фрагментов/пикселей, вершинных шейдерах, вычислительных шейдерах и т. д. Также она позволяет включать эффекты трассировки лучей — например, точные отражения и тени — в стандартный пайплайн растеризации. Ее можно использовать в вычислительном шейдере для реализации автономного рендерера на основе трассировки пути. ChameleonRT — автономный трассировщик путей, использующий подход вычислительных шейдеров для Metal.
Трассировка лучей в Metal выполняется следующим образом: вы загружаете свою геометрию, строите над ней примитивные структуры ускорения нижнего уровня, затем создаете инстансы, ссылающиеся на эти структуры, и строите структуру ускорения верхнего уровня поверх этих инстансов. Для рендеринга сцены нужно запустить вычислительный шейдер и непосредственно рейкасты в структуру ускорения верхнего уровня, чтобы получить возвраты от ее пересечений с лучами. Результаты пересечения несут данные о пересекающихся примитивах и геометрии, а при использовании инстансов — и об инстансах. Затем ваш шейдер ищет геометрические данные об объекте, в который попал рейкаст, и закрашивает его, после чего можно продолжить процесс трассировки пути.
В настоящее время Metal поддерживает только встроенную трассировку лучей, в отличие от DirectX и Vulkan, которые также обеспечивают поддержку программной трассировки. Она, в свою очередь, используется для реализации автономных средств рендеринга трассировки лучей — именно этот подход ChameleonRT использует в DirectX и Vulkan. OptiX поддерживает только программную трассировку лучей, что требует создания таблицы привязки шейдеров (Shader Binding Table, SBT) для предоставления API таблицы функций, вызываемых при пересечении определенных объектов в сцене. SBT трудно настраивать и отлаживать, однако их потенциальное преимущество в том, что так графический процессор получает возможность переупорядочивать и группировать вызовы функций для уменьшения расхождения потоков. При встроенной трассировке лучей разработчику необходимо произвести все это вручную или вовсе от этого отказаться (подробнее см. другое видео с WWDC20).
Те, кто уже знаком с Metal, наверняка помнят предыдущий алгоритм расчета пересечения лучей. Новая встроенная поддержка трассировки лучей пошла еще дальше, позволяя рендереру полностью перейти на ГП. Предыдущий алгоритм собирал пакеты лучей, находил пересечения в сцене и записывал полученные результаты в память. То есть, нужно было запустить несколько вычислительных шейдеров для отслеживания первичных лучей и создания теневых и вторичных, затем отследить теневые лучи и продолжить вторичные и после этого произвести фильтрацию завершенных контуров. Для этого требуется значительно больший объем памяти и вычислений, что приводит к повышенной нагрузке на рендерер. Такой подход также не очень хорошо подходит для дополнения стандартных пайплайнов растеризации эффектами трассировки лучей. Подобные решения хороши для рендеринга сложных фильмов и могут быть эффективно реализованы с помощью встроенной трассировки лучей. Например, оно используется в Hyperion от Disney. Вот отличное видео, объясняющее, как это работает.
Трассировка лучей в Metal во многом похожа на другие API, но оптимизирована для более простого использования. Например, для сравнения приведем код, необходимый для сборки и сжатия BVH в DirectX или Vulkan и Metal. API OptiX обеспечивает аналогичное упрощение — вот ссылка на сборку BVH в OptiX в качестве примера. Также приятным бонусом идет возможность иметь шаблоны и функциональные возможности стилей C++ в языке шейдеров — это функция Metal, использующая CUDA для кода на стороне устройства.
Однако в этой простоте есть и свои недостатки. Например, в то время как в DirectX, Vulkan и OptiX вы можете контролировать, где выделяется память для структуры ускорения, Metal вам не оставляет никакого выбора. В результате вы не можете выделить структуры ускорения в MTLHeap и поэтому, чтобы убедиться, что они доступны для вашего пайплайна рендеринга, вы должны сами пометить их как используемые в цикле — вместо простого вызова useHeap.
// Использование структуры ускорение верхнего уровня
[command_encoder setAccelerationStructure:bvh->bvh atBufferIndex:1];
// Помечаем все структуры ускорения мэшей как используемые
for (auto &mesh : bvh->meshes) <
[command_encoder useResource:mesh->bvh usage:MTLResourceUsageRead];
Если у вас много BVH нижнего уровня, как это бывает в сценах с большим количеством инстансов, могут возникнуть дополнительные нагрузки. Было бы неплохо иметь возможность выделить структуры ускорения в куче и заменить этот цикл одним [commandencoder useHeap: dataheap-> heap];
Этот API также значительно упрощается за счет того, что он не включает программную трассировку лучей и требует только структуру в виде таблицы привязки шейдеров при реализации настраиваемых геометрий или других операций, которые должны выполняться во время обхода (например, cutout). Код для управления настройкой SBT в DirectX, Vulkan и OptiX составляет значительную часть вспомогательного кода в бэкэнде для каждого API, и хорошо, что этого нет в Metal, не работающем с настраиваемой геометрией или cutout текстурами. Однако в модели SBT графический процессор может группировать или переупорядочивать вызовы функций, но это меньше касается встроенной трассировки лучей, в случае которой такая информация недоступна для драйвера. Действительно ли текущие драйверы для DirectX, Vulkan и OptiX на это способны – вопрос к разработчикам, но теоретически это возможно. В конце концов, вы можете обнаружить, что реализуете что-то вроде более простого аналога SBT для поиска необходимых данных о примитивах/мэшах/инстансах в вашей сцене в буферах аргументов, как это реализовано в ChameleonRT. Тогда же вам необходимо реализовать операции, происходящие во время обхода (настраиваемая геометрия, прозрачность cutout).
Быстрая трассировка лучей на ЦП с библиотеками Intel
В результатах CineBench от AnandTech можно заметить, что CineBench использует Embree — библиотеку трассировки лучей на ЦП от Intel, обеспечивающую оптимизированный обход структуры ускорения и ядер пересечения примитивов, оказывая такую же нагрузку на ЦП, что и новые API трассировки лучей на ГП. Embree была выпущена в 2011 году и с тех пор нашла широкое применение в кино, науке и других сферах.
ChameleonRT также поддерживает бэкэнд Embree, использующий Embree для быстрого обхода лучей и пересечения примитивов, ISPC — для программирования SIMD и TBB — для многопоточности. На самом деле, запустить его на M1 Arm довольно просто. Существует AArch64/NEON порт Embree — Embree-aarch64, — недавно получивший обновления от команды Apple с целью добавления AVX2 в бэкэнд NEON. Embree в значительной степени оптимизирован для ширины SIMD, равной 8, поэтому, даже несмотря на то, что в данном случае нужно использовать 2 вектора NEON, чтобы он действовал как один вектор AVX2, так можно обеспечить лучшую производительность, чем бэкэнд шириной 4 на NEON.
ISPC — компилятор для программирования SIMD на ЦП, в котором пишутся скалярные программы, компилирующиеся для параллельной работы — по одному экземпляру программы на векторную дорожку. Каждая программа обрабатывает свои фрагменты данных параллельно с другими программами. Это что-то вроде GLSL или HLSL, работающих на ЦП, где скалярная программа выполняется параллельно с использованием SIMD. ОднакоISPC уже поддерживает NEON и AArch64, так что включение в него комбинации macOS+AArch64/NEON оказалось довольно простым. Для этого можно использовать такой PR.
Наконец, хотя TBB — библиотека Intel для многопоточности, она не имеет никакого отношения к конкретной архитектуре ЦП. Все, что нам нужно, — это собрать TBB для AArch64.
Бенчмарки
Теперь, когда ChameleonRT работает на ЦП и ГП чипа M1, можно провести несколько тестов. Для сравнения аналогичные тесты были проведены на i7-1165G7 в XPS 13 (тут стоит заметить, что у него могут возникнуть проблемы с нагреванием), на i7-4790K и на i9-9920X на Ubuntu. Что касается ГП, для сравнения был взят RTX 2070. Непосредственно M1 использовался с 16 ГБ оперативной памяти Mac Mini.
Для начала приведем цифры CineBench, о которых говорилось ранее:
Источник