2016-09-17 4 views
2

난 왼쪽으로 이동하고 바이트를 추가하려면 제로 128 비트 레지스터가 있습니다. 나는 다음과 같이 그것을 바꿀 수있다 :16 바이트를 XMM 레지스터로 이동하는 방법 (최대)?

pslldq xmm0, 1 

...하지만 지금은 빈 공간에 알을 복사하고 싶다. 예 :

or xmm0, al 

물론 작동하지 않습니다. 나는 영향을받은 가장 낮은 8 비트 만 원한다. 이것은 레지스터의 채우기에 연속적인 값인 al이 사용되는 루프에 있습니다. 그래서 저는 일종의 mov 교육이나 다른 대안이 필요합니다.

좌상 8 비트를 삽입하고 삽입하는 단일 명령이 이상적입니다. 그런 생각은 아닙니다.

저는 x86-64 명령어 세트 데이터에서 많은 시간을 낭비했지만, 원하는 것을 할 수있는 것을 찾을 수 없었습니다. 할 수 있습니까?

업데이트 : pinrb를 시도한 후 코드 논리에 오류가 있음을 발견했습니다. pinsrb는 훌륭하지만 불행하게도 레지스터가 아닌 즉각적인 인덱스 만 사용할 수 있습니다.

연속되지 않는 위치에서 바이트를 가져 와서 한 번에 한 바이트 씩 바이트를 처리해야한다고 생각합니다. 바이트 수는 1에서 16까지 가능합니다. 첫 번째 바이트 I 잡는 바이트는 xmm0의 최하위 바이트로 끝나야하고 다음 바이트는 그 다음으로 가장 낮은 바이트로갑니다.

+1

SSE4.1'pinsrb xmm0, eax, 1'을 원하지만 그 16 번 반복은 느립니다. 매번 벡터를 이동하는 대신 16 개의 다른 인덱스로 사용하십시오. –

+0

index = 0, 1, 2, ...와 함께 pinsrb를 사용할 수 있도록 삽입 루프를 푸십시오 (종료 테스트를 유지). 좀 더 효율적으로 작업 할 수 있습니다 (특히 총 바이트 수 삽입 할 것입니다.)하지만 작동 할 것입니다. –

+0

주변 코드에 대해 너무 많이 알려지지 않았기 때문에 최적의 상황에 대한 구체적인 조언을 드릴 수는 없습니다 (예 : 셔플 처리량, 대기 시간, 처리량, 캐시 누락에 병목 현상이 있음 ...) 많은 바이트 캐리가 있습니까? 아니면 다른 많은 계산이 있습니까?) 어떤 경우에는 바이트를 16B 스크래치 배열에 복사하고 벡터로드를 수행하는 것이 가장 좋습니다 (예 : 상점 포워딩 실패는 문제가 아니었고 모든 상점은 문제가되지 않았습니다. –

답변

3

Intel's intrinsics guide은 벡터 명령어를 찾는 데 유용 할 수 있습니다. Intrinsic뿐만 아니라 asm 니모닉을 나열합니다 (검색 결과가 항목의 전체 텍스트와 일치하기 때문에 intrinsic 대신 니모 P을 사용하여 검색 할 수 있습니다).

인텔의 PDF 참조 설명서에도 색인이 있습니다. insn set ref 매뉴얼은 볼륨 2입니다. 태그 위키의 Intel 매뉴얼 링크를 참조하십시오.


PINSRB는 사용자가 요청한대로 정확하게 수행 할 수 있지만 그렇게하지 마십시오. 병합 명령어 (PINSR *)가있는 정수 -> 벡터 삽입은 삽입 위치의 인덱스를 사용하기 때문에 벡터를 왼쪽으로 이동할 필요가 없습니다. (그리고 매번 같은 위치를 사용하고 벡터를 이동하는 것은 성능에 좋지 않습니다.)

이 문제의 경우 : 벡터에 16 바이트를 별도로 삽입하는 것이 가장 효율적인 방법이 아닙니다. 정수 레지스터에 4 개 또는 8 개의 그룹으로 어셈블하는 것이 더 좋은 방법 일 수 있습니다.

;; b0 .. b15 are whatever addressing mode you want. 
;; if you could get more than 1 of b0..b15 with a single vector load (i.e. there is some locality in the source bytes) 
;; then DON'T DO THIS: do vector loads and shuffle + combine (pshufb if needed) 

movzx eax, byte [b0] 
mov ah, byte [b1] # partial-reg merging after this is free on Haswell, cheap on SnB/IvB, and very slow on CPUs before Sandybridge. 
movzx edx, byte [b2] 
mov dh, byte [b3] 
shl edx, 16 
or  edx, eax 
movd xmm0, edx  # cheaper than pinsrd xmm0, edx, 0. Also zeros the rest of the vector 

movzx eax, byte [b4] 
mov ah, byte [b5] 
movzx edx, byte [b6] 
mov dh, byte [b7] 
shl edx, 16 
or  edx, eax 
pinsrd xmm0, edx, 1 
... 
pinsrd xmm0, edx, 2 
... 
pinsrd xmm0, edx, 3 

SSE4를 사용할 수 없다면 pinsrw (SSE2)를 사용할 수 있습니다. 또는 movd과 셔플 벡터를 PUNPCKLDQ/PUNPCKLDQD과 함께 사용하는 것이 더 좋을 수도 있습니다. (이 링크는 Intel의 매뉴얼에서 HTML로 추출한 것입니다.)

Agner Fog's Optimizing Assembly guide (및 지침 테이블/마이크로 가이드)을 참조하여 어떤 명령 시퀀스가 ​​실제로 좋을 지 결정하십시오.

관련 문제