AVX指令集的详解

发布时间:2023-05-19

一、AVX指令集补丁

AVX指令集是Intel公司于2011年推出的一种SIMD指令集,它可以实现8个双精度浮点数或16个单精度浮点数的并行计算,从而加快向量运算的速度。但是,在使用AVX指令集时,有时候会出现处理器缺陷、操作系统错误或虚拟机中断等问题。为了解决这些问题,Intel发布了AVX指令集补丁。 使用AVX指令集的程序需要在寄存器和内存中存储更多的数据,因此会增加内存带宽和CPU功耗,可能导致CPU降频。AVX指令集补丁可以通过优化代码的方式降低CPU功耗,从而使CPU不会出现降频现象。 下面是一个使用AVX指令集的示例代码,可以通过使用AVX指令集补丁来降低CPU功耗:

#include <immintrin.h>
float sum(float *a, int n){
    __m256 vec_sum = _mm256_set1_ps(0.0f);
    for (int i = 0; i < n; i+=8) {
        __m256 vec_a = _mm256_loadu_ps(a+i);
        vec_sum = _mm256_add_ps(vec_sum, vec_a);
    }
    float sum[8] __attribute__((aligned(32)));
    _mm256_store_ps(sum, vec_sum);
    return sum[0] + sum[1] + sum[2] + sum[3]
         + sum[4] + sum[5] + sum[6] + sum[7];
}

二、AVX指令集是什么意思

AVX指令集(Advanced Vector Extensions)是Intel公司于2011年推出的一种向量扩展指令集,它可以实现更高效的并行计算和处理。AVX指令集在之前的SSE指令集的基础上增加了更多的指令和功能。 AVX指令集包括256位SIMD指令和128位SIMD指令。其中256位SIMD指令需要使用特定指令扩展集成的CPU才能够实现,而128位SIMD指令则可以在普通的x86架构CPU上运行。AVX指令集支持单精度浮点数、双精度浮点数和整数数据类型的向量运算。 下面是一个AVX指令集的示例代码,用于计算向量的平均值:

#include <immintrin.h>
float avg(float *a, int n){
    __m128 vec_sum = _mm_set1_ps(0.0f);
    for (int i = 0; i < n; i+=4) {
        __m128 vec_a = _mm_loadu_ps(a+i);
        vec_sum = _mm_add_ps(vec_sum, vec_a);
    }
    float sum[4] __attribute__((aligned(16)));
    _mm_store_ps(sum, vec_sum);
    return (sum[0] + sum[1] + sum[2] + sum[3]) / n;
}

三、AVX指令集降频

使用AVX指令集会增加CPU的功耗和温度,从而可能导致CPU降频,影响计算性能。为了降低CPU功耗,可以采取以下几个措施:

  1. 尽可能使用更高的制程工艺,以减少功耗和温度。
  2. 使用更好的散热系统,以提高CPU的散热效果。
  3. 使用AVX指令集补丁,优化代码的CPU占用率,减少功耗和温度。
  4. 使用降频软件或BIOS设置,降低CPU的频率,减少CPU的功耗和温度。 下面是一个使用AVX指令集并进行了降频优化的示例代码,可以通过设置CPU的频率来降低CPU功耗:
#include <immintrin.h>
#include <x86intrin.h>
float sum(float *a, int n){
    __m256 vec_sum = _mm256_set1_ps(0.0f);
    for (int i = 0; i < n; i+=8) {
        __m256 vec_a = _mm256_loadu_ps(a+i);
        vec_sum = _mm256_add_ps(vec_sum, vec_a);
    }
    float sum[8] __attribute__((aligned(32)));
    _mm256_store_ps(sum, vec_sum);
    return sum[0] + sum[1] + sum[2] + sum[3]
         + sum[4] + sum[5] + sum[6] + sum[7];
}
void freq_reduce(){
    const unsigned int MSR_PLATFORM_INFO = 0xCE;
    const unsigned int MSR_IA32_PERF_STATUS = 0x198;
    const unsigned int freq_max = 3000; // original frequency is 3300 MHz
    const unsigned int frequency_reduction = 10; // 10% frequency reduction
    int eax, ebx, ecx, edx;
    __asm__ __volatile__("cpuid"
        : "=a"(eax), "=b"(ebx), "=c"(ecx), "=d"(edx)
        : "a"(0x1), "c"(0x0)
    );
    if (ecx & (1 << 27)) { // if frequency reduction is supported
        unsigned int base_frequency = ebx & 0xFF; // MHz
        if (base_frequency >= freq_max) {
            unsigned int max_non_turbo_ratio = (eax >> 8) & 0xFF;
            unsigned int logical_proc_number = ((eax >> 16) & 0xFF) + 1;
            unsigned int temperature_target = (ecx >> 16) & 0xFF;
            unsigned int temperature_offset = edx & 0x7F;
            unsigned int frequency_low = (base_frequency * max_non_turbo_ratio
                * (100 - frequency_reduction)) / (100 * logical_proc_number);
            unsigned int msr = ((temperature_offset << 1) & 0xFF)
                | ((temperature_target << 8) & 0xFF00)
                | ((max_non_turbo_ratio << 24) & 0xFF000000);
            __asm__ __volatile__("wrmsr"
                :
                : "c"(MSR_PLATFORM_INFO), "a"(msr), "d"(0)
            );
            __asm__ __volatile__("rdmsr"
                : "=a"(eax), "=d"(edx)
                : "c"(MSR_IA32_PERF_STATUS)
            );
            unsigned int frequency_high = (eax & 0xFF) * base_frequency;
            unsigned int frequency = (frequency_low < frequency_high)
                ? frequency_low : frequency_high;
            msr = ((msr & 0xFFFFFFFFU) & ~0x1FFU)
                | ((frequency * logical_proc_number) / max_non_turbo_ratio);
            __asm__ __volatile__("wrmsr"
                :
                : "c"(MSR_IA32_PERF_STATUS), "a"(msr), "d"(0)
            );
        }
    }
}
int main(){
    float a[1024];
    for(int i=0;i<1024;i++) a[i]=1.0f;
    freq_reduce();
    for(int i=0;i<1000000;i++) sum(a,1024);
    return 0;
}

四、AES指令集

AES指令集是Intel公司于2010年推出的一种硬件加速指令集,用于加密和解密数据。AES指令集可以在无需外部加密芯片的情况下进行AES加密和解密,从而加快数据处理速度。 AES指令集可以生成随机数和伪随机数,以及安全的Hash值,还可以进行SHA加密。使用AES指令集可以有效地保护计算机系统的安全性。 下面是一个使用AES指令集进行AES加密和解密的示例代码:

#include <wmmintrin.h>
#include <stdio.h>
int main()
{
    __m128i key128 = _mm_set_epi32(0x12345678, 0x90abcdef, 0x87654321, 0xcdef0123);
    __m128i data128 = _mm_set_epi32(0x08070605, 0x04030201, 0x88776655, 0x44332211);
    __m128i encrypted = _mm_aesenc_si128(data128, key128);
    __m128i decrypted = _mm_aesdec_si128(encrypted, key128);
    printf("Encrypted: %08X%08X%08X%08X\n", _mm_extract_epi32(encrypted, 3), _mm_extract_epi32(encrypted, 2), _mm_extract_epi32(encrypted, 1), _mm_extract_epi32(encrypted, 0));
    printf("Decrypted: %08X%08X%08X%08X\n", _mm_extract_epi32(decrypted, 3), _mm_extract_epi32(decrypted, 2), _mm_extract_epi32(decrypted, 1), _mm_extract_epi32(decrypted, 0));
    return 0;
}