Что делает Apple PowerPC memcpy настолько быстрым?
Я написал несколько функций копирования в поисках хорошей стратегии памяти на PowerPC. Использование регистров Altivec или fp с подсказками кеша (dcb *) удваивает производительность по сравнению с простым байтовым циклом копирования для больших данных. Первоначально довольный этим, я бросил регулярную memcpy, чтобы увидеть, как он сравнивается... в 10 раз быстрее, чем мой лучший! Я не собираюсь переписывать memcpy, но я надеюсь научиться этому и ускорить несколько простых фильтров изображений, которые тратят большую часть времени на перемещение пикселей в память и из памяти.
Акустический анализ показывает, что их внутренний цикл использует dcbt для предварительной выборки, с 4-мя векторными чтениями, затем записывается 4 вектора. После настройки моей лучшей функции, чтобы также перехватить 64 байта на итерацию, преимущество производительности memcpy по-прежнему неловко. Я использую dcbz для освобождения полосы пропускания, Apple ничего не использует, но оба кода имеют тенденцию колебаться в магазинах.
prefetch
dcbt future
dcbt distant future
load stuff
lvx image
lvx image + 16
lvx image + 32
lvx image + 48
image += 64
prepare to store
dcbz filtered
dcbz filtered + 32
store stuff
stvxl filtered
stvxl filtered + 16
stvxl filtered + 32
stvxl filtered + 48
filtered += 64
repeat
Есть ли у кого-нибудь идеи о том, почему очень похожий код имеет такой драматический разрыв в производительности? Я бы хотел помассировать настоящие фильтры изображений в любом секретном соусе, который использует memcpy!
Дополнительная информация: Все данные выравниваются по вектору. Я делаю отфильтрованные копии изображения, не заменяя оригинал. Код работает на PowerPC G4, G5 и Cell PPU. Версия Cell SPU уже безумно быстро.
Ответы
Ответ 1
Акустический анализ показывает, что их внутренний цикл использует dcbt для предварительной выборки, с 4-мя векторными чтениями, затем записывается 4 вектора. После настройки моей лучшей функции, чтобы также перехватить 64 байта на итерацию
Я могу заявить очевидное, но, поскольку в вашем вопросе не упоминается следующее: возможно, стоит указать:
Я бы пообещал, что выбор Apple из 4 векторов, за которыми следуют 4 вектора, пишет так же, как и с конвейером G5, порядок выполнения заказа в "группах отправки" , поскольку он имеет магический 64-байтовый идеальный размер линии. Вы заметили, что линия пропускает в Nick Bastin ссылку bcopy.s? Это означает, что разработчик подумал о том, как поток команд будет потребляться G5. Если вы хотите воспроизвести одну и ту же производительность, недостаточно прочитать данные по 64 байта за раз, вы должны убедиться, что ваши группы команд заполнены (в основном, я помню, что инструкции могут быть сгруппированы до пяти независимых, первые четыре - инструкции без прыжка, а пятый - только прыжок. Подробности сложнее).
EDIT: вас также может заинтересовать следующий параграф на той же странице:
Инструкция dcbz по-прежнему выравнивает 32 байтовые сегменты памяти в соответствии с G4 и G3. Однако, поскольку это не полная кегли на G5, у него не будет преимуществ в производительности, на которые вы, вероятно, надеялись. Существует инструкция dcbzl, недавно введенная для G5, которая нулевая полная 128-байтная шкала.
Ответ 2
Я не знаю точно, что вы делаете, так как я не могу видеть ваш код, но секретный соус Apple - здесь.
Ответ 3
Возможно, это из-за кэширования процессора. Попробуйте запустить CacheGrind:
Cachegrind - это профилировщик кеша. Это выполняет детальное моделирование I1, D1 и L2 в вашем CPU и поэтому можно точно определить источники пропусков кеша в вашем коде. Это определяет количество промахов в кэше, ссылки на память и инструкции выполняется для каждой строки исходного кода, с функцией, для каждого модуля и резюме всей программы. Это полезно с программами, написанными на любом языке. Cachegrind запускает программы о 20-100x медленнее, чем обычно.
Ответ 4
Все еще не ответ, но вы подтвердили, что memcpy фактически перемещает данные? Возможно, это было просто перепрограммированное копирование на запись. Вы все равно увидите внутренний цикл memcpy в Shark, поскольку часть первой и последней страниц действительно скопирована.
Ответ 5
Как уже упоминалось в другом ответе, "dcbz", как определено Apple на G5, работает только на 32 байтах, поэтому вы потеряете производительность с этой инструкцией на G5, который имеет 128 байтов. Вам нужно использовать "dcbzl", чтобы предотвратить кэширование адресата из памяти (и эффективно сократить полезную ширину памяти для чтения в два раза).