2012-10-21 4 views
4

효율적으로 256 비트 벡터의 요소에 액세스하려면 어떻게해야합니까? 예를 들어256 비트 ps 벡터의 구성 요소에 액세스하는 방법

c = _mm256_dp_ps(a, b, 0xff); 

으로 내적을 계산 한 다음 어떻게 값을 액세스 할 수 있습니까? 나는 높은 부분과 낮은 부분 모두를 얻을 필요가 내가 처음과 같은 128 개 비트 부품을 추출 할 필요가 있음을 제대로 이해하지 :

r0 = _mm256_extractf128_ps(c,0); 
r1 = _mm256_extractf128_ps(c,1); 

만 다음 추출 수레 :

_MM_EXTRACT_FLOAT(fr0, r0, 0); 
_MM_EXTRACT_FLOAT(fr1, r1, 0); 

return fr0 + fr1; 
+3

단일 점 제품에 대해 많은 패킹/압축 풀기를 수행하는 경우 해당 데이터를 최소한으로 유지하려면 관련 코드를 다시 설계하는 것이 좋습니다. – Mysticial

+0

제안을 환영합니다. 16 개의 부동 소수점 벡터에 대해 내적을 계산해야합니다. AVX 경로가 나에게 최선의 선택 인 것 같지만 실제로 코드에 만족하지 않습니다. –

+0

각 벡터가 메모리에서 연속적입니까? – Mysticial

답변

-1

효율적인 방법은 없습니다. dp_ps 작업 자체가 느리고 후속 추출이 느립니다. 일괄 적으로 더 많은 데이터를 처리 할 수 ​​없다면 SSE4 명령어를 사용하여 내적을 계산하고 256 비트보다 128 비트로 작동하는 것이 더 빠릅니다.

+1

당신은 단지 이것을하는 법만 물었고, 그것을하는 법은 아니었다. 나는 몇 가지를 게시했다. 배치 도트 제품을 수행하는 코드 예제는 SSE4보다 빠르고 빨라질 수 있습니다. 또한, 단일 점 제품의 결과를 얻는 두 가지 다른 방법. –

4

글쎄, 당신 단지 메모리에 저장 한 후 스칼라와 함께 일할 수 : 당신은이처럼 256 비트 레지스터의 하단에 상단을 교환하고 추가 할 수

float v[8]; 
*(__m256)(v) = _mm256_dp_ps(a, b, 0xff); 
float result = v[0] + v[4]; 

:

__m256 c = _mm256_dp_ps(a, b, 0xff); 
__m256 d = _mm256_permute2f128_ps(c, c, 1); 
__m256 result = _mm256_add_ps(c, d); 

두 옵션 중 어느 것보다 훨씬 빠를 확률은 4x 8 와이드 도트 제품을 한 번에 줄이고 함께 줄이는 것입니다. 스케치 :

d0 = _mm256_dp_ps(a[0], b[0], 0xff); 
d1 = _mm256_dp_ps(a[1], b[1], 0xff); 
d2 = _mm256_dp_ps(a[2], b[2], 0xff); 
d3 = _mm256_dp_ps(a[3], b[3], 0xff); 

d01 = _mm256_permute_ps(d0, d1, ...); 
d23 = _mm256_permute_ps(d2, d3, ...); 
d= _mm256_permute_ps(d01, d23, ...); 

d0123upper = _mm256_permute2f128_ps(d0123, d0123, 1); 
d = _mm256_add_ps(d0123upper, d0123); // lower 128 bits contain the results of 4 8-wide dot products 
+0

더 빠른 옵션을 이해하지 못했지만 어떻게 이들을 치환 할 수 있습니까? d01 = _mm256_permute_ps (d0, d1, ...); 이 메서드는 오직 하나의 레지스터를 발견한다 – Shahar

+0

@Shahar d0에 부동 소수점 d0.0, d0.1에서 d0.8이 포함되어 있고 d1에 d1.0, d1.1에서 d1.8 등이 포함 된 경우 d0123에는 d0.0, d1이 포함되어야한다. .0, d2.0, d3.0, d0.4, d1.4, d2.4, d3.4. 내가 언급 한 내장 함수가 그 일을하지는 않지만, 어떤 종류의 순열 (permutation)이 될 필요가 있음을 안다. 제안은 환영한다;) –