2016-02-12 2 views
1

Что является наиболее эффективным способом для загрузки регистра 64 YMM сКакой эффективный способ загрузки регистра x64 ymm с 4 отдельными двойными?

  1. 4 двойниками равномерно разнесенных т.е. непрерывного набора двойников

    0 1 2 3 4 5 6 7 8 9 10 .. 100 
    And i want to load for example 0, 10, 20, 30 
    
  2. 4 двойников в любом положении

    i.e. i want to load for example 1, 6, 22, 43 
    
+0

Можно ли считать, что AVX2 доступен, или вам нужно только решение AVX? –

+0

Моими пристрастиями я должен был заявить, что было бы неплохо иметь решение AVX. –

ответ

5

Самый простой способ - VGATHERQPD, который является инструкцией по AVX2 на Haswell и выше.

VGATHERQPD ymm1, [rsi+xmm7*8], ymm2 

Использование индексов DWORD, указанные в vm32x, собирать значения дважды предварительно cision FP из памяти кондиционированной по маске, указанной ymm2. Условно собранные элементы объединены в ymm1.

, который может достичь этого с помощью одной инструкции. Здесь ymm2 - это регистр маски с наивысшим битом, указывающий, должно ли оно быть скопировано в ymm1 или нет (осталось без изменений). ymm7 содержит индексы элементов с коэффициентом масштабирования.

Так приложенный к вашим примерам, это может выглядеть в синтаксисе MASM:

4 двойников равномерно разнесенных т.е. непрерывного набора двойников

-1 2 3 4 5 6 7 8-10 .. 100 --- И я хочу, чтобы загрузить, например, 0, 10, 20, 30

.data 
    .align 16 
    qqIndices dq 0,10,20,30 
    dpValues REAL8 0,1,2,3, ... 100 
.code 
    lea rsi, dpValues 
    movapd ymm7, qqIndices 
    vpcmpeqw ymm1, ymm1      ; set to all ones 
    vgatherqpd ymm0, [rsi+xmm7*8], ymm1 

Теперь ymm0 содержит четыре двухместных 0, 10, 20, 30. Хотя, я еще не проверял это. Другое дело, что это не обязательно самый быстрый выбор в каждом сценарии. Значения все собраны отдельно, это означает, что каждое значение требуется один доступ к памяти, см How are the gather instructions in AVX2 implemented

Так, по Mysticial's comment

Недавно я должен был сделать то, что требуется истинное собрать нагрузку. (т. е. данные [индекс [i]]). На Haswell, 4 index loads + 2x movsd + 2x movhpd + vinsertf128 все еще значительно быстрее, чем ymm load + vgatherqpd. Таким образом, даже в лучшем случае, 4-сторонняя сборка все еще теряет.Однако я не пробовал использовать 8-way.

самый быстрый способ будет использовать этот подход.

Таким образом, «эффективный» в способе OpCode будет использовать VGATHER, и «эффективный», связанный с временем выполнения, будет последним (пока давайте посмотрим, как будут работать будущие архитектуры).

EDIT: согласно комментариям инструкции VGATHER ускоряются на Broadwell и Skylake.

+1

Удивительный ответ, спасибо. –

+0

'VPGATHERDD' (8-way gather) медленнее, чем последовательность' movd'/'pinsrd' на Haswell. Бродвелл быстрее собирает, а Скайлак еще быстрее. Я не уверен, где находится переломный момент. Кроме того, не загружайте вектор all-ones. Используйте 'vpcmpeqw ymm1, ymm1' для генерации константы. –

1

Я думаю, что вам нужно искать работу GATHER как VGATHERQPD.

Инструкция условно загружает до 2 или 4 значений с плавающей запятой с двойной точностью из адресов памяти, указанных операндом памяти (вторым операндом), и использует индексы qword. Операнд памяти использует форму VSIB байта SIB для указания операнда регистров общего назначения в качестве общей базы, векторного регистра для массива индексов относительно базы и коэффициента постоянной шкалы.

Обратите внимание, что для этого требуется AVX2, поэтому неприменим к мосту Sandy Bridge/Ivy Bridge, который имеет AVX, но не AVX2.

+0

Да, конечно. Я забыл упомянуть об этом. – ErmIg

 Смежные вопросы

  • Нет связанных вопросов^_^