Обновить

Комментарии 15

Монументальный труд, спасибо! Есть же люди, которым не лень учить других!

Вопрос: а если я использую NumPy, там всё эффективно реализовано?

numpy при сборке ищет BLAS/LAPACK. Если Apple BLAS найдётся при сборке, то будет эффективно.

В miniconda, кажись, numpy собран с openblas, а там есть реализация с использованием ARM SME2, так что должно работать, но я не проверял.

Наблюдаются странности со временем выполнения при размерностях матриц, равных степени двойки.

А на маке есть инструменты, позволяющие замерить доступы/миссы по кешам (типа perf в Linux)? Есть подозрение, что при "круглых" размерах разные доступы попадают в один и тот же set кеша и ассоциативности не хватает, чтобы разрулить конфликты - но это только предположение, детально код не смотрел и в любом случае при возможности лучше явно измерить.

Главный инструмент в macOS для оценки производительности Xcode Instruments, но у меня с ним как-то раньше не задалось. Надо бы протестить, но код из статьи только с целью разобраться, что да как устроено и понять насколько код написанный "на коленке" хуже чем то, что реализовано производителем в BLAS. Так что результат меня устраивает и больше тратить время на эту задачу не хочется)

Вот это статья, так статья. Статьища! Хабр - торт

Спасибо!

Подскажите, "заполненные матрицы" в большинстве мест в статье и "плотные матрицы" в одном из заголовков ("Базовый вариант умножения плотных матриц") - это же синонимы? Это два варианта перевода dense matrix?

Да, все верно, я приводил к единообразию, но похоже что-то пропустил

Спасибо за статью, было интересно прочитать. Ранее в рамках интереса выполнял похожую задачу с разницей того, что это всё не на CPU а на GPU используя OpenCL/CUDA. Если кому-то интересно, исследовательскую работу провел товарищ из Европы - https://cnugteren.github.io/tutorial/pages/page1.html

Большая была разница в производительности между CUDA и OpenCL?

Потрясающая статья, большое спасибо. На Apple M4 10 core такие циферки при первом запуске:


 Start ZIG MM mult benchmark f32 

 ----------------------------

 M = 3000, N = 3000, K = 4000,  NB = 96, NTHREADS = 1

 ----------------------------

 V00             check = 9002396026.1525,     time =    22.491209      GF/sec =         2.98

 V01             check = 9002396026.1525,     time =     2.228460      GF/sec =        30.09

 ARM sme exampl  check = 9002396026.1352,     time =     0.296731      GF/sec =       225.98

 V02 sme         check = 9002396026.1352,     time =     0.416260      GF/sec =       161.09

 V03 SME+L1L2    check = 9002396026.1352,     time =     0.161521      GF/sec =       415.15

 V04 SME+L1L2x2  check = 9002396026.1352,     time =     0.086962      GF/sec =       771.09

 V05 SME+L1L2x4  check = 9002396026.1352,     time =     0.050918      GF/sec =      1316.92

 V06 SME+MAX     check = 9002396026.1352,     time =     0.054740      GF/sec =      1224.97

--------------

 Apple BLAS      check = 9002396026.1352,     time =     0.046933      GF/sec =      1428.74

Спасибо за тест, рад, что все работает!

Результаты совпадают с тем, что выдает мой:

Start ZIG MM mult benchmark f32
 ----------------------------
 M = 3000, N = 3000, K = 4000,  NB = 96, NTHREADS = 1
 ----------------------------
 V00             check = 8998229076.8414,     time =    22.893146      GF/sec =         2.93
 V01             check = 8998229076.8414,     time =     2.212305      GF/sec =        30.31
 ARM sme exampl  check = 8998229076.8095,     time =     0.291058      GF/sec =       230.38
 V02 sme         check = 8998229076.8095,     time =     0.418173      GF/sec =       160.35
 V03 SME+L1L2    check = 8998229076.8095,     time =     0.167515      GF/sec =       400.29
 V04 SME+L1L2x2  check = 8998229076.8095,     time =     0.089717      GF/sec =       747.41
 V05 SME+L1L2x4  check = 8998229076.8095,     time =     0.050723      GF/sec =      1321.98
 V06 SME+MAX     check = 8998229076.8095,     time =     0.052684      GF/sec =      1272.78
--------------
 Apple BLAS      check = 8998229076.8095,     time =     0.045733      GF/sec =      1466.22

Запустите еще, пожалуйста, с параметром --nt=4 и --nt=10

zig build --release=fast run -- --m=3000 --n=3000 --k=4000 --nt=4
zig build --release=fast run -- --m=3000 --n=3000 --k=4000 --nt=10


При N=4096 падение производительности относительно N=4095 и N=4097 составляет 2.5 раза, при этом функции от Apple работают стабильно, то есть это известная проблема, и у неё есть решение.
Если у кого-то есть понимание или предположения, с чем это связано, пожалуйста, поделитесь в комментариях.

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

Спасибо за наводку, почитаю про это

Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации