벡터의 모든 요소를 추가하기 위해 인라인 함수를 구현했지만 비 SIMD 추가보다 빠르지는 않습니다.내 AVX2 가로 덧셈 기능이 비 SIMD 추가보다 빠르지 않은 이유는 무엇입니까?
선언 :이 벡터의 모든 int 값을 추가 내 두 가지 방법
#define N 128
#define M N
int __attribute__((aligned(32)))temp8[8];
__m256i vec;
int __attribute__((aligned(32))) c_result[N][M];
:
첫째, 비 SIMD 버전은 다음과 같습니다
_mm256_store_si256((__m256i *)&temp8[0] , vec);
c_result[i][j]= temp8[0]+temp8[1]+temp8[2]+temp8[3]+temp8[4]+temp8[5]+temp8[6]+temp8[7];
둘째, AVX2 버전 :
c_result[i][j] =_mm256_hadd2_epi32(vec);
나는 이런 식으로 hadd2을 구현 :
// my horizontal addition of epi32
inline int _mm256_hadd2_epi32(__m256i a)
{
__m256i a_hi;
a_hi = _mm256_permute2x128_si256(a, a, 1); //maybe 1 should be 4
a = _mm256_hadd_epi32(a, a_hi);
a = _mm256_hadd_epi32(a, a);
a = _mm256_hadd_epi32(a, a);
return _mm256_extract_epi32(a,0);
}
내가 gcc
, Linux-mint
, skylake
마이크로 아키텍처를 사용합니다.
는 나는 다음과 같은 이유로이 될 수 추측 : 이 특히 요소의 순서를 변경하는 적어도 하나의 사이클을 필요로 치환이 제한 벡터 실행 유닛과 달리 fastly 추가됩니다 스카이 레이크 마이크로 아키텍처의 정수 4 ALU
이어서 hadd
지침이 이어집니다. 문제는, 내가 놓친 것이거나 모든 요소를 추가하기 위해 SIMD를 사용할 필요가 없다는 것입니다.
업데이트 : 방금 MUL 프로그램을 저장소 에 추가하여 매트릭스 곱셈의 전체 코드에 액세스 할 수 있습니다. 비 -IMD 버전을 사용하면 경과 시간은 201 ns가되고 SIMD 버전에서는210 ns가됩니다.
한 걸음 물러서서 왜 이런 수평 작업을 할 필요가 있는지 물어보십시오. 그렇다면 정말 성능에 중대한 병목 현상이 생길 수 있습니다. 일반적으로 루프 후 수평 작업 만 수행하면됩니다 (예 : 일반적으로 중요하지 않은 축소의 최종 단계로서 성능 측면에서 중요합니다. –
@PaulR, 당신 말이 맞아요. 이런 식으로 병목 현상이 발생하는 것은 아닙니다. 그리고 저는 비 SIMD 및 AVX2 버전의 성능을 직접 테스트하고 싶었습니다. 물론 그것은 연구 및 교육 목적을위한 것입니다. 하지만 그 대답이 나를 도울 것입니다. 왜냐하면 3,5,7 및 9 인접 요소가 병목 구역에 수평으로 추가되어야하는 Convolution Matrix Kernel을 구현했기 때문입니다. – Martin
최적화는 그보다 조금 더 복잡합니다. Agner Fog 매뉴얼에 대한 링크는 x86 태그 위키를 참조하십시오. 프론트 엔드, 생성 된 uops, 포트, 지연 시간 및 침투를 고려해야합니다. * perf *로 코드를 프로파일 링 했습니까? –