Страницы

Поиск по вопросам

суббота, 30 ноября 2019 г.

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

#cpp #ассемблер #x64 #x86 #x86_64


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


Есть ли смысл писать программу таким образом, что б абсолютно все используемые массивы,
переменные и т.п. в оперативной памяти занимали 
строго последовательные адреса? Т.е. например: начальный адрес 90870000, конечный
90880000. Есть смысл что б этом промежутке были исключительно данные конкретной программы?
Как влияет на скорость программы соотношение размера кэшей и используемого размера
оперативной памяти?
Есть ли смысл обработку данных во много раз больших размера кэшей проводить блоками?
Каждый блок меньше размера кэша.
В ассемблере есть инструкции по записи в оперативную память без использования кэша.
Какой в этом смысл?
Какую из двух инструкций и в каких случаях использовать для возврата 128 бит результата
обработки обратно в память?

     movdqu [ebx],xmm0
     movntps [ebx],xmm0//без использования кэша



Правильно я понимаю, что если эти 128 бит больше не нужны для обратотки, то лучше
movntps? Это быстрее?


Предположим есть чернобелое bmp изображение 1024*1024.
Перенесем все его пиксели в:

    unsigned __int8 *src_img
    src_img = new unsigned __int8[1024*1024];//каждый байт это значение одного пикселя
от 0 до 255



Допустим есть два варианта алгоритма:
1) копируем в xmm0 128 бит из src_img, что-то делаем в xmm регистрах и возвращаем
измененные 128бит обратно по тому же адресу в оперативную память. Самое важное эти
128 бит выбираются от начала src_img последовательно до конца.
2) Делаем тоже самое, но 128 бит выбираются не последовательно,а из разных мест src_img
1-й вариант будет быстрее или нет? Или формулируя по другому: первоначально программа
берет данные из: movdqu xmm0,[ebx]. Имеет различие для быстродействия насколько далеко
от первоначального адреса программа берет следующие 128 бит? 

Изучаю данные вопросы в контексте вот этой задачи:
https://stackoverflow.com/questions/50747393/prewitt-edge-detection-algorithm-using-x86-mmx-simd
    


Ответы

Ответ 1



Есть смысл что б этом промежутке были исключительно данные конкретной программы? Это зависит от программы. Если она оч. часто обращается к этим переменным, то да, конечно - размещение всех ее данных в блоке, который занимает минимальное к-во кеш-линий, ускорит эти операции. Обычно не говорят о размещении всех данных в одной кеш-линии. На практике это невозможно. Обычно говорят о "кратном рамере" блока данных. Как влияет на скорость программы соотношение размера кэшей и используемого размера оперативной памяти? Особой разницы с первым вопросом не вижу. Если у Вас программа оптимизирована под загрузку кеша, и учитывает его размер, конечно, она будет быстрее работать на железе с большим кешем. Надеюсь, Вы так же вкурсе, что кеши есть разных уровней (level1, level2, level3, кеш данных, кеш инструкций), их размеры могут отличаться, и скорость доступа к ним, естественно, тоже разная, т.е. поле для оптимизаций - обширное настолько, насколько Вам хватит терпения перебирать различное железо для экспериментов и фантазии на реализацию алгоритмов. Есть ли смысл обработку данных во много раз больших размера кэшей проводить блоками? Каждый блок меньше размера кэша. Нет. Есть смысл распараллелить эту обработку между ядрами таким образом, чтобы у каждого ядра эти порции данных, по возможности, не пересекались. Вот тут кратность размера обрабатываемого блока данных имеет большое значение. Порции следует разделить так, чтобы кеш-линии одного ядра не пересекались с кеш-линиями другого. В ассемблере есть инструкции по записи в оперативную память без использования кэша. Какой в этом смысл? Смысл в том, чтобы не делать лишнюю работу: если Вам нужно только переместить блок данных, и Вы не обращаетесь к нему для каких-то рассчетов, то и в кеш его нет необходимости загружать. Имеет различие для быстродействия насколько далеко от первоначального адреса программа берет следующие 128 бит? Нет, не должно. На 64битных кеш-линиях, по крайней мере, последовательное чтение 128битных значений в непараллельной программе выгоды не дает. В этом случае определяющим будет размер кеша и параллелизм между ядрами (кооперация кэшей). Ждите или ищите 256битных кеш линий, по крайней мере :)

Комментариев нет:

Отправить комментарий