AVX2 初探

AVX2 初探Intel最近发布了AVX-512,据说对浮点运算有很大提升,我的机器目前不支持AVX-512,但是支持AVX2,按照之前Intel给出的数据,据说能提速将近8倍:IntroductiontoIntel®AdvancedVectorExtensions测试环境可能这篇文章有点偏老,我这边也想验证一下没有优化的C/C++浮点运算和AVX2优化后的浮点运算到底快多少。这是我机器的配置:Manufacturer GenuineIntelName IntelCorei77820

大家好,又见面了,我是你们的朋友全栈君。

Intel最近 发布了AVX-512,据说对浮点运算有很大提升,我的机器目前不支持AVX-512,但是支持AVX2,按照之前Intel给出的数据,据说能提速将近8倍:
Introduction to Intel® Advanced Vector Extensions
在这里插入图片描述

测试环境

可能这篇文章有点偏老,我这边也想验证一下没有优化的C/C++浮点运算和AVX2优化后的浮点运算到底快多少。这是我机器的配置:

Manufacturer GenuineIntel
Name Intel Core i7 7820HQ
Codename Kaby Lake
Specification Intel® Core™ i7-7820HQ CPU @ 2.90GHz
Max frequency 3900 MHz
Instructions sets MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, EM64T, VT-x, AES, AVX, AVX2, FMA3, TSX

测试代码

我用的编译器是VS2017,这是对应的测试代码 :

#include <stdio.h>
#include <immintrin.h>
#include <random>
#include <chrono>

#define NUM_FLOATS 102400000

int main()
{ 
   
	// At first, prepare 2 float arrays
	float* fas = new float[NUM_FLOATS];
	float* fbs = new float[NUM_FLOATS];
	float* fcs = new float[NUM_FLOATS];

	std::random_device rd;
	std::mt19937 gen(rd());
	std::uniform_real_distribution<float> dis(-1.0f, 1.0f);

	for (int i = 0; i < NUM_FLOATS; i++)
	{ 
   
		fas[i] = dis(gen);
		fbs[i] = dis(gen);
	}

	// Begin to do the AVX operation
	__m256 ymm0, ymm1;

	auto tp0 = std::chrono::high_resolution_clock::now();

#if 0
	for (int i = 0; i < NUM_FLOATS / 8; i++)
	{ 
   
		ymm0 = _mm256_loadu_ps(fas + (i << 3));
		ymm1 = _mm256_loadu_ps(fbs + (i << 3));

		ymm0 = _mm256_mul_ps(ymm0, ymm1);

		_mm256_storeu_ps(fcs + (i << 3), ymm0);
	}

#else
	for (int i = 0; i < NUM_FLOATS; i++)
	{ 
   
		fcs[i] = fas[i] * fbs[i];
	}
#endif

	// Finish doing the AVX operation

	auto tp1 = std::chrono::high_resolution_clock::now();

	printf("It takes %lld msec to finish %d round of float multiply.\n",
		std::chrono::duration_cast<std::chrono::milliseconds>(tp1 - tp0).count(), NUM_FLOATS);

	for (int i = 0; i < 10; i++)
	{ 
   
		printf("%f*%f = %f\n", fas[i], fbs[i], fcs[i]);
	}

	delete[] fas;
	delete[] fbs;
	delete[] fcs;

	return -1;
}

中间有一个条件编译模块,可以在AVX2和C/C++之间做切换,我随机选了102,400,000(一亿个单精度浮点数字左右)进行乘法运算。

测试结果

这是对应的测试结果:

C/C++代码 AVX2代码
不使用缺省编译器优化 第一次:347ms
第二次:298ms
第三次:296ms
第一次:154ms
第二次:153ms
第三次:151ms
使用缺省编译器优化 第一次:120ms
第二次:119ms
第三次:117ms
第一次:116ms
第二次:119ms
第三次:162ms

结论

可以看出来, VS2017对浮点有做比较好的优化,估计我测试的这种场景比较简单,编译器对这种情况做了很好的优化,基本上和自己用AVX指令写出来的性能差不多。
如果不用编译器优化,这个时候,AVX2大概比普通的C/C++浮点运算代码快2倍左右,不像宣传的那样厉害嘛。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/139128.html原文链接:https://javaforall.net

(0)
上一篇 2022年5月30日 上午11:46
下一篇 2022年5月30日 上午11:46


相关推荐

  • Android实现两次按下返回键退出「建议收藏」

    Android实现两次按下返回键退出

    2022年2月6日
    56
  • CNN卷积神经网络及图像识别

    CNN卷积神经网络及图像识别CNN卷积神经网络及图像识别前言神经网络(neualnetworks)是人工智能研究领域的一部分,当前最流行的神经网络是深度卷积神经网络(deepconvolutionalneuralnetworks,CNNs),虽然卷积网络也存在浅层结构,但是因为准确度和表现力等原因很少使用。目前提到CNNs和卷积神经网络,学术界和工业界不再进行特意区分,一般都指深层结构的卷积神经网络,层数从”几层“到”几十上百“不定。CNNs目前在很多很多研究领域取得了巨大的成功,例如:语音识别,图像识别,图像分割,

    2022年6月6日
    36
  • java-初始化数组

    java-初始化数组Java 语言中数组必须先初始化 然后才可以使用 所谓初始化 就是为数组的数组元素分配内存空间 并为每个数组元素赋初始值 能不能只分配内存空间 不赋初始值呢 不行 一旦为数组的每个数组元素分配了内存空间 每个内存空间里存储的内容就是该数组元素的值 即使这个内存空间存储的内容为空 这个空也是一个值 null 不管以哪种方式来初始化数组 只要为数组元素分配了内存空间 数组元素就具有了初始值 初始值的获得有两种形式 一种由系统自动分配 另一种由程序员指定 数组在初始化数组的同时 可以指定数组的大小 也可以

    2026年3月26日
    2
  • 32 64 peb结构体

    32 64 peb结构体NTDLL Test TEB nbsp nbsp 0x000NtTib nbsp nbsp nbsp nbsp nbsp nbsp NT TIB nbsp nbsp 0x038Environ Ptr64Void nbsp nbsp 0x040ClientI nbsp nbsp nbsp nbsp CLIENT ID nbsp nbsp 0x050ActiveR nbsp Ptr64Void nbsp nbsp 0x058ThreadL

    2026年3月16日
    2
  • Spring缓存注解@Cacheable、@CacheEvict、@CachePut使用

    Spring缓存注解@Cacheable、@CacheEvict、@CachePut使用转自 http tom seed iteye com blog 缓存注解有以下三个 Cacheable nbsp nbsp nbsp CacheEvict nbsp nbsp nbsp CachePut nbsp Cacheable value accountCache 这个注释的意思是 当调用这个方法的时候 会从一个名叫 accountCache 的缓存中查询 如果没

    2026年3月18日
    2
  • Android中bindService的使用方法

    Android中bindService的使用方法bindService用于绑定一个服务。这样当bindService(intent,conn,flags)后,就会绑定一个服务。这样做可以获得这个服务对象本身,而用startService(intent)的方法只能启动服务。   bindService方式的一般过程:①新建Service类BindService。在BindService类里新建内部类MyBinder,继承自Bind

    2022年6月6日
    33

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号