在下面的代码中,我改变了“dataLen”,导致效率不同。
dataLen = 400 SSE时间:758000微秒 AVX时间:483000微秒 SSE > AVX
dataLen = 2400 SSE时间:4212000微秒 AVX时间:2636000微秒 SSE > AVX
dataLen = 2864 SSE时间:6115000微秒 AVX时间:6146000微秒 SSE ~= AVX
dataLen = 3200 SSE时间:8049000微秒 AVX时间:9297000微秒 SSE < AVX
dataLen = 4000 SSE时间:10170000微秒 AVX时间:11690000微秒 SSE < AVX
SSE和AVX代码可以简化为:buf3 [i] + = buf1 [1] * buf2 [i];
dataLen = 400 SSE时间:758000微秒 AVX时间:483000微秒 SSE > AVX
dataLen = 2400 SSE时间:4212000微秒 AVX时间:2636000微秒 SSE > AVX
dataLen = 2864 SSE时间:6115000微秒 AVX时间:6146000微秒 SSE ~= AVX
dataLen = 3200 SSE时间:8049000微秒 AVX时间:9297000微秒 SSE < AVX
dataLen = 4000 SSE时间:10170000微秒 AVX时间:11690000微秒 SSE < AVX
SSE和AVX代码可以简化为:buf3 [i] + = buf1 [1] * buf2 [i];
#include "testfun.h"
#include <iostream>
#include <chrono>
#include <malloc.h>
#include "immintrin.h"
using namespace std::chrono;
void testfun()
{
int dataLen = 4000;
int N = 10000000;
float *buf1 = reinterpret_cast<float*>(_aligned_malloc(sizeof(float)*dataLen, 32));
float *buf2 = reinterpret_cast<float*>(_aligned_malloc(sizeof(float)*dataLen, 32));
float *buf3 = reinterpret_cast<float*>(_aligned_malloc(sizeof(float)*dataLen, 32));
for(int i=0; i<dataLen; i++)
{
buf1[i] = 1;
buf2[i] = 1;
buf3[i] = 0;
}
//=========================SSE CODE=====================================
system_clock::time_point SSEStart = system_clock::now();
__m128 p1, p2, p3;
for(int j=0; j<N; j++)
for(int i=0; i<dataLen; i=i+4)
{
p1 = _mm_load_ps(&buf1[i]);
p2 = _mm_load_ps(&buf2[i]);
p3 = _mm_load_ps(&buf3[i]);
p3 = _mm_add_ps(_mm_mul_ps(p1, p2), p3);
_mm_store_ps(&buf3[i], p3);
}
microseconds SSEtimeUsed = duration_cast<milliseconds>(system_clock::now() - SSEStart);
std::cout << "SSE time used: " << SSEtimeUsed.count() << " us, " <<std::endl;
//=========================AVX CODE=====================================
for(int i=0; i<dataLen; i++) buf3[i] = 0;
system_clock::time_point AVXstart = system_clock::now();
__m256 pp1, pp2, pp3;
for(int j=0; j<N; j++)
for(int i=0; i<dataLen; i=i+8)
{
pp1 = _mm256_load_ps(&buf1[i]);
pp2 = _mm256_load_ps(&buf2[i]);
pp3 = _mm256_load_ps(&buf3[i]);
pp3 = _mm256_add_ps(_mm256_mul_ps(pp1, pp2), pp3);
_mm256_store_ps(&buf3[i], pp3);
}
microseconds AVXtimeUsed = duration_cast<milliseconds>(system_clock::now() - AVXstart);
std::cout << "AVX time used: " << AVXtimeUsed.count() << " us, " <<std::endl;
_aligned_free(buf1);
_aligned_free(buf2);
}
我的CPU是英特尔Xeon E3-1225 v2,它有一个L1缓存32KB*4(4个核心)。当运行此代码时,只使用了1个核心,因此使用的L1缓存为32KB。
buf1、buf2和buf3足够小,可以放在L1缓存和L2缓存(L2缓存1MB)中。SSE和AVX都受带宽限制,但随着数据长度的增加,为什么AVX需要比SSE更长的时间?