>백엔드 개발 >C++ >최신 x86-64 Intel CPU에서 사이클당 4개의 FLOP를 달성하는 방법은 무엇입니까?

최신 x86-64 Intel CPU에서 사이클당 4개의 FLOP를 달성하는 방법은 무엇입니까?

Susan Sarandon
Susan Sarandon원래의
2024-12-14 08:42:10147검색

How to Achieve 4 FLOPs Per Cycle on Modern x86-64 Intel CPUs?

사이클당 이론상 최대 4개의 FLOP를 달성하는 방법은 무엇입니까?

이론적으로 4개의 부동 소수점의 최고 성능을 달성하는 것이 가능합니다. 다음을 활용하여 최신 x86-64 Intel CPU에서 주기당 작업(이중 정밀도)을 수행합니다. 기술:

SSE 명령에 대한 코드 최적화

  • 여러 데이터 요소의 병렬 처리를 가능하게 하는 SSE(Streaming SIMD Extensions) 명령을 사용합니다.
  • 최적의 SSE를 위해 코드가 올바르게 정렬되었는지 확인하세요.

루프 풀기 및 인터리빙

  • 내부 루프를 풀면 명령어 수준 병렬 처리가 향상됩니다.
  • 인터리브는 곱셈과 더하기를 더합니다. CPU의 파이프라이닝을 활용하기 위해

작업을 3개로 그룹화

  • 일부 Intel CPU의 실행 단위에 맞게 작업을 3개 그룹으로 배열합니다. 이를 통해 add 및 mul 명령을 교대로 수행하여 처리량을 최대화할 수 있습니다.

불필요한 중단 및 종속성 방지

  • 중단을 방지하기 위해 명령 간의 데이터 종속성을 최소화합니다. .
  • 불필요한 부분을 식별하고 제거하려면 컴파일러 최적화(-O3 이상)를 사용하세요. dependency.

예제 코드

다음 코드 조각은 Intel Core i5 및 Core i7 CPU에서 최고에 가까운 성능을 달성하는 방법을 보여줍니다.

#include <emmintrin.h>
#include <omp.h>
#include <iostream>
using namespace std;

typedef unsigned long long uint64;

double test_dp_mac_SSE(double x, double y, uint64 iterations) {
    register __m128d r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, rA, rB, rC, rD, rE, rF;

    // Generate starting data.
    r0 = _mm_set1_pd(x);
    r1 = _mm_set1_pd(y);

    r8 = _mm_set1_pd(-0.0);

    r2 = _mm_xor_pd(r0, r8);
    r3 = _mm_or_pd(r0, r8);
    r4 = _mm_andnot_pd(r8, r0);
    r5 = _mm_mul_pd(r1, _mm_set1_pd(0.37796447300922722721));
    r6 = _mm_mul_pd(r1, _mm_set1_pd(0.24253562503633297352));
    r7 = _mm_mul_pd(r1, _mm_set1_pd(4.1231056256176605498));
    r8 = _mm_add_pd(r0, _mm_set1_pd(0.37796447300922722721));
    r9 = _mm_add_pd(r1, _mm_set1_pd(0.24253562503633297352));
    rA = _mm_sub_pd(r0, _mm_set1_pd(4.1231056256176605498));
    rB = _mm_sub_pd(r1, _mm_set1_pd(4.1231056256176605498));

    rC = _mm_set1_pd(1.4142135623730950488);
    rD = _mm_set1_pd(1.7320508075688772935);
    rE = _mm_set1_pd(0.57735026918962576451);
    rF = _mm_set1_pd(0.70710678118654752440);

    uint64 iMASK = 0x800fffffffffffffull;
    __m128d MASK = _mm_set1_pd(*(double*)&iMASK);
    __m128d vONE = _mm_set1_pd(1.0);

    uint64 c = 0;
    while (c < iterations) {
        size_t i = 0;
        while (i < 1000) {
            // Main computational loop

            r0 = _mm_mul_pd(r0, rC);
            r1 = _mm_add_pd(r1, rD);
            r2 = _mm_mul_pd(r2, rE);
            r3 = _mm_sub_pd(r3, rF);
            r4 = _mm_mul_pd(r4, rC);
            r5 = _mm_add_pd(r5, rD);
            r6 = _mm_mul_pd(r6, rE);
            r7 = _mm_sub_pd(r7, rF);
            r8 = _mm_mul_pd(r8, rC);
            r9 = _mm_add_pd(r9, rD);
            rA = _mm_mul_pd(rA, rE);
            rB = _mm_sub_pd(rB, rF);

            r0 = _mm_add_pd(r0, rF);
            r1 = _mm_mul_pd(r1, rE);
            r2 = _mm_sub_pd(r2, rD);
            r3 = _mm_mul_pd(r3, rC);
            r4 = _mm_add_pd(r4, rF);
            r5 = _mm_mul_pd(r5, rE);
            r6 = _mm_sub_pd(r6, rD);
            r7 = _mm_mul_pd(r7, rC);
            r8 = _mm_add_pd(r8, rF);
            r9 = _mm_mul_pd(r9, rE);
            rA = _mm_sub_pd(rA, rD);
            rB = _mm_mul_pd(rB, rC);

            r0 = _mm_mul_pd(r0, rC);
            r1 = _mm_add_pd(r1, rD);
            r2 = _mm_mul_pd(r2, rE);
            r3 = _mm_sub_pd(r3, rF);
            r4 = _mm_mul_pd(r4, rC);
            r5 = _mm_add_pd(r5, rD);
            r6 = _mm_mul_pd(r6, rE);
            r7 = _mm_sub_pd(r7, rF);
            r8 = _mm_mul_pd(r8, rC);
            r9 = _mm_add_pd(r9, rD);

위 내용은 최신 x86-64 Intel CPU에서 사이클당 4개의 FLOP를 달성하는 방법은 무엇입니까?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.