我正在尝试编写一个 C++ 程序,它启动我在 x64 汇编程序中编写的函数。我想稍微加快速度(并利用 CPU 功能),所以我选择使用向量运算。
问题是,我必须将正弦乘以一个整数,所以我必须首先计算正弦。在 SSE/AVX 中可以做到这一点吗?我知道指令fsin,但它不仅在 FPU 中,而且它一次只计算 1 个正弦。所以我必须将它推入 FPU,调用fsin,将其从 FPU 弹出到内存,然后将其放入 AVX 寄存器。在我看来,这不值得这么麻烦。
我正在尝试使用不同的方法来将函数应用于数组.
_mm_sin_ps不知道我的范围,但是_mm_sqrt_ps?
我怎么知道?并编译它没有错误.
#include <random>
#include <iostream>
#include <cmath>
#include <chrono>
#include <algorithm>
#include <valarray>
#include "immintrin.h"
#include <array>
int main()
{
std::cout<<"start\n";
std::random_device rd;
std::mt19937 gen(rd());
std::uniform_real_distribution<> dis(-1000, 1000);
int N=100;
while(N--)
{
std::cout<<"\nN: "<<N;
const int T1=4E6;
{
int T=T1,T0=T1/4;
std::array<float,T1> array;
while(T--)
{
array[T]=dis(gen);
}
auto start_time = std::chrono::high_resolution_clock::now();
auto it =array.begin();
while(T0--)
{
__m128 X = _mm_loadu_ps(it);
__m128 result = _mm_sin_ps(X);
_mm_storeu_ps(it, result);
it+=4;
}
auto time2=std::chrono::high_resolution_clock::now()-start_time;
std::cout<<"\nintr1: "<<std::chrono::duration_cast<std::chrono::microseconds>(time2).count();
}
} …Run Code Online (Sandbox Code Playgroud) 我正在尝试exponential使用SIMD 计算函数。我发现了这个功能:https : //software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_exp_ps&expand=2136
我已经将其包含"immintrin.h"在代码中,并且我的cpu也有一个SSE标志。但是gcc在抱怨error: ‘_mm_exp_pd’ was not declared in this scope
如何检查SVML指令是否启用?
我发现 MSVC 的 zmmintrin.h 副本定义了用于计算 __m512 32 位浮点向量和 __m512d 双向量的逆立方根的函数
_mm512_invcbrt_ps();
_mm512_invcbrt_pd();
Run Code Online (Sandbox Code Playgroud)
然而,这些函数在《Intel Intrinsics Guide》中没有出现: https: //software.intel.com/sites/landingpage/IntrinsicsGuide/
不过,它们似乎没有在微软的网站上列出,请参阅:https://learn.microsoft.com/en-us/cpp/intrinsics/compiler-intrinsics ?view=msvc-160
我知道平方根反比有序列内在函数:
_mm512_invsqrt_ps();
_mm512_invsqrt_pd();
Run Code Online (Sandbox Code Playgroud)
我知道AVX有逆立方根序列内在函数:
_mm256_invcbrt_ps();
_mm256_invcbrt_pd();
Run Code Online (Sandbox Code Playgroud)
_mm512_invcbrt_ps()也是如此;和_mm512_invcbrt_pd(); 微软特定的还是英特尔真的忘记记录它们的内在函数之一?!?
我必须多次将 10 提高到两倍的幂。
有没有比使用数学库更有效的方法来做到这一点pow(10,double)?如果重要的话,我的双打总是在 -5 到 -11 之间为负。
我假设 pow(double,double) 使用比 pow(10,double) 所需的更通用的算法,因此可能不是最快的方法。鉴于下面的一些答案,这可能是一个不正确的假设。
至于为什么,是对数插值。我有一个 x 和 y 值表。我的对象有一个已知的 x 值(几乎总是双精度值)。
double Dbeta(struct Data *diffusion, double per){
double frac;
while(per>diffusion->x[i]){
i++;
}
frac = (per-diffusion->x[i-1])/(diffusion->x[i]-diffusion->x[i-1]);
return pow(10,log10DB[i-1] + frac * (log10DB[i]-log10DB[i-1]));
}
Run Code Online (Sandbox Code Playgroud)
这个函数被调用了很多次。我被告知要研究分析,所以这就是我首先要做的。
我刚刚被告知我可以使用自然对数代替以 10 为底的,这显然是正确的。(我的愚蠢有时甚至让我自己感到惊讶。)
用自然对数替换所有内容后,一切都运行得更快了。通过分析(这是我今天学到的一个新词),我发现 39% 的代码都用在了 exp 函数中,所以对于那些想知道这部分是否真的阻碍了我的代码的人来说,它是。
c++ ×3
simd ×3
sse ×3
intrinsics ×2
avx ×1
avx512 ×1
c ×1
optimization ×1
performance ×1
pow ×1
trigonometry ×1
visual-c++ ×1
windows ×1
x86 ×1
x86-64 ×1