我需要一个简单的浮点舍入函数,因此:
double round(double);
round(0.1) = 0
round(-0.1) = 0
round(-0.9) = -1
Run Code Online (Sandbox Code Playgroud)
我能找到ceil()和floor()在math.h中-但不是round().
它是以另一个名称存在于标准C++库中,还是缺少?
SSE2具有在单精度浮点数和32位整数之间转换向量的指令.
_mm_cvtps_epi32()_mm_cvtepi32_ps()但是没有双精度和64位整数的等价物.换句话说,他们失踪了:
_mm_cvtpd_epi64()_mm_cvtepi64_pd()似乎AVX也没有它们.
模拟这些内在函数的最有效方法是什么?
我正在寻找在SSE元素上运算的指数函数的近似值.即 - __m128 exp( __m128 x ).
我有一个快速但实际上准确度非常低的实现:
static inline __m128 FastExpSse(__m128 x)
{
__m128 a = _mm_set1_ps(12102203.2f); // (1 << 23) / ln(2)
__m128i b = _mm_set1_epi32(127 * (1 << 23) - 486411);
__m128 m87 = _mm_set1_ps(-87);
// fast exponential function, x should be in [-87, 87]
__m128 mask = _mm_cmpge_ps(x, m87);
__m128i tmp = _mm_add_epi32(_mm_cvtps_epi32(_mm_mul_ps(a, x)), b);
return _mm_and_ps(_mm_castsi128_ps(tmp), mask);
}
Run Code Online (Sandbox Code Playgroud)
任何人都可以以更快的速度(或更快)获得更高精度的实现吗?
如果我用C风格写的话,我会很高兴的.
谢谢.
我正在寻找在AVX元件(单精度浮点)上运行的指数函数的有效(快速)近似.即 - __m256 _mm256_exp_ps( __m256 x )没有SVML.
相对精度应该类似于~1e-6,或~20个尾数位(1 ^ 2 ^ 20).
如果用英特尔内在函数用C风格编写,我会很高兴.
代码应该是可移植的(Windows,macOS,Linux,MSVC,ICC,GCC等).
这类似于使用SSE的指数函数的最快实现,但是这个问题寻求非常快速且精度低(当前的答案提供了大约1e-3的精度).
此外,这个问题是寻找AVX/AVX2(和FMA).但请注意,这两个问题的答案很容易在SSE4 __m128或AVX2 之间移植__m256,因此未来读者应根据所需的精度/性能权衡进行选择.
我正在寻找快速SSE低精度(~1e-3)指数函数.
我遇到了这个很好的答案:
/* max. rel. error = 3.55959567e-2 on [-87.33654, 88.72283] */
__m128 FastExpSse (__m128 x)
{
__m128 a = _mm_set1_ps (12102203.0f); /* (1 << 23) / log(2) */
__m128i b = _mm_set1_epi32 (127 * (1 << 23) - 298765);
__m128i t = _mm_add_epi32 (_mm_cvtps_epi32 (_mm_mul_ps (a, x)), b);
return _mm_castsi128_ps (t);
}
Run Code Online (Sandbox Code Playgroud)
根据Nicol N. Schraudolph的工作:NN Schraudolph."指数函数的快速,紧凑近似." Neural Computation,11(4),1999年5月,pp.853-862.
现在我需要一个"双精度"版本:__m128d FastExpSSE (__m128d x).这是因为我不控制输入和输出精度,这恰好是双精度,并且两次转换double - > float,then float - > double占用了50%的CPU资源.
需要做哪些改变?
我天真地试过这个:
__m128i double_to_uint64(__m128d x) { …Run Code Online (Sandbox Code Playgroud) 在现代x86_64 CPU上,AVX/SSE指数需要多少个时钟周期?
我是这样的: pow(x, y) = exp(y*log(x))
即两者兼而有之exp(),log()AVX x86_64指令需要一定的已知周期数?
_mm256_exp_ps()_mm256_log_ps()或者循环次数可能会根据指数级别而变化,是否有最大循环次数可以进行成本求幂?
我已经开始使用SSE优化我的代码.基本上它是一个光线跟踪器,通过在__m128数据类型x,y,z中存储坐标,一次处理4条光线(四条光线的坐标按轴分组).但是,我有一个分支语句,可以防止除以零,我似乎无法转换为SSE.连续这是:
const float d = wZ == -1.0f ? 1.0f/( 1.0f-wZ) : 1.0f/(1.0f+wZ);
Run Code Online (Sandbox Code Playgroud)
其中wZ是z坐标,需要对所有四条射线进行计算.
我怎么能把它翻译成SSE?
我一直在尝试使用SSE等于比较如下(现在wz属于__m128数据类型,包含四条光线中每条光线的z值):
_mm_cmpeq_ps(_mm_set1_ps(-1.0f) , wZ )
Run Code Online (Sandbox Code Playgroud)
然后使用它来识别wZ [x] = -1.0的情况,取这个情况的绝对值,然后继续计算正常.
但是,我在这方面没有取得多大成功.
c++ ×5
sse ×5
simd ×4
avx ×3
exponential ×2
x86 ×2
avx2 ×1
c ×1
intrinsics ×1
optimization ×1
precision ×1
rounding ×1
x86-64 ×1