В принципе, если операнды в кэше, то это должно быть правильно. Но вот в моем случае предсказать сколько будет извлекаться операнд из памяти не получается.
Посмотрел ваш код. Вы ничего не предприняли для улучшения работы кеша. Вам помогло то, что матрицы 320х320, которые реально умножаются после Штрассена, помещаются в кеш 2-го уровня. В моём коде порядок умножения такой, что кеш 1-го уровня активно используется.
А именно, я умножаю сначала первые 32 строки матрицы B на все строки матрицы A, потом следующие 32 строки матрицы B, и т.д. В результате практически всё время нужные элементы матрицы B лежат в кеше 1-го уровня, а не 2-го, как у вас. Ещё лучше этот метод работает, если матрица не помещается целиком даже в кеш 2-го уровня, как если не использовать Штрассен.
Именно. С регистрами надо колдовать, чтобы их хватило. Я написал в блоге, что именно происходит в моей процедуре: большие блоки делятся на блоки 2x2, которые перемножаются за 1 такт (8 умножений + 4 сложения через paddwd). За одно обращение к памяти извлекаются сразу 2 матрицы 2x2, за второе - еще две, и за третье - еще две. Далее, первые две умножаются на вторые две, а потом на третьи две, итого 32 умножения и всего три обращения. Всего 0.75 обращений на 8 умножений.
В результате ваш цикл разбавлен кучей инструкций pshufd, а они тоже занимают время.
Сравните, на каждые 4 полезные pmaddwd и 4 полезные paddd лишних операций:
в моём коде: 5 чтений из памяти (кеша), причём одно чтение совмещено с pmaddwd,
в вашем: 3 чтения, 6 pshufd, и 2 пересылки в xmm регистрах.