SSE2 извлекает данные из упакованных данных в golang
Я пишу функцию сборки на Голанге. Для упрощения предположим, что я хочу сделать следующую функцию:
func sseSumOfMinimums (d1, d2 [2]float64) float64
Он вычислит минимум d1 [0], d2 [0] и минимум d1 [1] и d2 [1] и вычислит сумму
По сборке делаю:
TEXT ·sseSum(SB), $0-40
MOVUPD d1+0(FP), X0 // loading d1 to X0
MOVUPD d2+16(FP), X1 // loading d1 to X1
MINPD X0, X1 // compute pair minimums and store to X1
MOVSD X1, X2 // move first min to X2
// How do I move second float of X1 to X3?
ADDSD X2, X3
MOVSD X3, ret+32(FP)
Часть, которую мне не хватает, это как извлечь второй скаляр из X1 в X3
1 ответ
Go не гарантирует выравнивание стека, чтобы вы могли использовать операнд источника памяти для minpd
?
Кроме того, я не знаком с Go; это его float
действительно бинарный IEEE64, который большинство языков (включая x86 asm) называют double
? Странно видеть float
в источнике и pd
(упакованный двойной) инструкции, используемые в ассемблере.
Затраты на вызов автономной рукописной asm-функции для этого будут выше, чем разрешение компилятору делать это с помощью скаляра. minsd
, для одной пары. Особенно с дрянным соглашением о вызовах Go, передавая аргументы в памяти и сохраняя возвращаемое значение в памяти.
Оптимизирующий компилятор Go с внутренним LLVM или gcc должен выполнить работу со встроенным кодом с меньшей задержкой и меньшим количеством мопов пропускной способности, чем вызов этой функции, даже с оптимизацией, приведенной ниже. Или, если вам повезет, компилятор будет использовать minpd
для тебя.
Но для актуальной проблемы, после minpd x0, x1
, что вам нужно, это горизонтальная сумма xmm1
, Самый быстрый способ сделать горизонтальную векторную сумму с плавающей запятой на x86.
Вы должны использовать movaps
скопировать регистры xmm, даже если вы заботитесь только о младших 64 битах. movsd x1, x2
сливается с младшими 64 битами xmm2, создавая ложную зависимость от старого значения и стоило случайного увеличения.
minpd x0, x1
movhps x1, x0 // high 64 bits of xmm1 => low 64 of xmm0
addsd x1, x0
Вы могли бы movaps x1, x2
а также unpckhpd x2,x2
, но это будет стоить дополнительно movapd
или же movaps
которого вы можете избежать, используя movhps
,
(movaps
/ movups
короче чем movapd
, меньший размер кода, а в остальном точно соответствует movapd
/ movupd
на всех процессорах для загрузки, хранения и reg-reg копий.)