通过编码是否有任何(非微优化)性能增益
float f1 = 200f / 2
Run Code Online (Sandbox Code Playgroud)
在比较中
float f2 = 200f * 0.5
Run Code Online (Sandbox Code Playgroud)
几年前我的一位教授告诉我,浮点除法比浮点乘法慢,但没有详细说明原因.
这句话适用于现代PC架构吗?
UPDATE1
关于评论,请同时考虑这个案例:
float f1;
float f2 = 2
float f3 = 3;
for( i =0 ; i < 1e8; i++)
{
f1 = (i * f2 + i / f3) * 0.5; //or divide by 2.0f, respectively
}
Run Code Online (Sandbox Code Playgroud)
更新2 从评论中引用:
[我想]知道什么是算法/架构要求导致>除法在硬件上比复制要复杂得多
我正在阅读这份文件:http://software.intel.com/en-us/articles/interactive-ray-tracing
我偶然发现了这三行代码:
SIMD版本已经快了很多,但我们可以做得更好.英特尔为SSE2指令集添加了快速1/sqrt(x)函数.唯一的缺点是它的精度有限.我们需要精度,所以我们使用Newton-Rhapson来改进它:
__m128 nr = _mm_rsqrt_ps( x );
__m128 muls = _mm_mul_ps( _mm_mul_ps( x, nr ), nr );
result = _mm_mul_ps( _mm_mul_ps( half, nr ), _mm_sub_ps( three, muls ) );
Run Code Online (Sandbox Code Playgroud)
此代码假定存在名为"half"(四次0.5f)和变量"three"(四次3.0f)的__m128变量.
我知道如何使用牛顿拉夫森计算函数的零点,我知道如何使用它来计算一个数的平方根,但我看不出这些代码如何执行它.
有人可以向我解释一下吗?
有谁知道为什么GCC/Clang不会在下面的代码示例中优化函数test1,只是在使用fast-math选项时只使用RCPPS指令?是否有另一个编译器标志会生成此代码?
typedef float float4 __attribute__((vector_size(16)));
float4 test1(float4 v)
{
return 1.0f / v;
}
Run Code Online (Sandbox Code Playgroud)
您可以在此处查看已编译的输出:https://goo.gl/jXsqat
我正在尝试重振使用3DNow的旧Win32游戏!指令集进行3D渲染.
在像Win7这样的现代操作系统上 - 不允许像FPADD或FPMUL这样的Win10指令,程序会抛出异常.
自从3DNow的数量!游戏使用的指令非常有限,在我的VS2008 MFC程序中,我试图使用向量异常处理来获取MMX寄存器的值,模拟3DNow!C代码指令并将值推回处理器3DNow!寄存器.
到目前为止,我成功完成了前两个步骤(我从ExceptionInfo->ExtendedRegisters偏移量为32的字节数组中获取mmx寄存器值并使用浮点类型C指令进行计算),但我的问题是,无论我如何尝试更新MMX寄存器值的寄存器价值似乎保持不变.
假设我的_asm陈述可能是错误的,我还使用这样的简单语句进行了一些最小的测试:
_asm movq mm0 mm7
Run Code Online (Sandbox Code Playgroud)
执行此语句没有其他例外,但在检索MMX寄存器值时,我仍然发现原始值未更改.
如何使作业有效?
具体来说,这是我正在讨论的代码:
float InvSqrt(float x) {
float xhalf = 0.5f*x;
int i = *(int*)&x; // warning: strict-aliasing UB, use memcpy instead
i = 0x5f375a86- (i >> 1);
x = *(float*)&i; // same
x = x*(1.5f-xhalf*x*x);
return x;
}
Run Code Online (Sandbox Code Playgroud)
我忘了我从哪里得到这个,但它显然比原来的 Quake III 算法(魔法常数略有不同)更好、更高效或更精确,但这个算法创建以来已经有 20 多年了,我只是想知道它是否是就性能而言,或者如果有一条指令已经在现代 x86-64 CPU 中实现了它,那么仍然值得使用它。
To introduced myself to x86 intrinsics (and cache friendliness to a lesser extent) I explicitly vectorized a bit of code I use for RBF (radial basis function) -based grid deformation. Having found vsqrtpd to be the major bottleneck I want to know if/how I can mask its latency further. This is the scalar computational kernel:
for(size_t i=0; i<nPt; ++i)
{
double xi = X[i], yi = X[i+nPt], zi = X[i+2*nPt];
for(size_t j=0; j<nCP; ++j)
{
// compute distance from i …Run Code Online (Sandbox Code Playgroud) 我一直在努力开始使用AVX2指令而运气不好(这个功能列表很有帮助).最后,我得到了我的第一个程序编译和做我想要的.我必须做的程序需要两个,u_char并且复合了两个.本质上,我使用它来解码存储在相机的u_char数组中的数据,但我认为这与此问题无关.
获得double两者的过程u_char是:
double result = sqrt(double((msb<<8) + lsb)/64);
Run Code Online (Sandbox Code Playgroud)
where msb和lsb是u_char具有最高有效位(msb)的两个变量和要计算的较低有效位(lsb)double.数据被存储在表示行主矩阵,其中的阵列msb和lsb值编码列的i分别是在第二和第三行.我用和不用AVX2编码了这个:
void getData(u_char* data, size_t cols, std::vector<double>& info)
{
info.resize(cols);
for (size_t i = 0; i < cols; i++)
{
info[i] = sqrt(double((data[cols + i] << 8) + data[2 * cols + i]) / 64.0);
;
}
}
void getDataAVX2(u_char* data, size_t cols, std::vector<double>& info)
{ …Run Code Online (Sandbox Code Playgroud) 中点细分算法[第93(104)页]的工作原理是将一条线分成更小的段,并测试每个段以查找它们是否在剪切区域的可见边界内。
在二分搜索算法中,我们找到中间元素,然后选择右侧或左侧。
但是,如下图所示,在第一次分割之后,我们发现这两个小节实际上都是有争议的。因此,它们都是进一步细分的候选者。所以,我们不能像二分查找那样进行。

我正在使用迭代方法。但是,下面的代码不起作用:
Line2d GetClippedLine()
{
Line2d clippingCandidate = this->line;
std::vector<Line2d> lines = clippingCandidate.GetMidpointSubLines();
while(lines[0] != lines[1])
{
lines = clippingCandidate.GetMidpointSubLines();
Line2d one = lines[0];
Line2d two = lines[1];
if(one.IsClippingCandidate(rectangle))
{
clippingCandidate = one;
}
if(two.IsClippingCandidate(rectangle))
{
clippingCandidate = two;
}
if(one.IsVisible(rectangle))
{
Coordinates2d::Draw(one, Yellow);
}
if(two.IsVisible(rectangle))
{
Coordinates2d::Draw(two, Yellow);
}
clippingCandidate.Show();
//std::cout<<"++";
//two.Show();
std::cout<<"\n";
}
return clippingCandidate;
}
Run Code Online (Sandbox Code Playgroud) 很高兴 gcc 编译器 4.8 带有带有 -Ofast 选项的 AVX 优化。但是,我发现了一个有趣但愚蠢的错误,它增加了不必要的额外计算。也许我错了,所以有人可以给我一个解释吗?
原来的C++源代码如下:
#define N 1000007
float a[N],b[N],c[N],d[N],e[N];
int main(int argc, char *argv[]){
cout << a << ' ' << b << ' ' << c << endl;
for(int x=0; x<N; ++x){
c[x] = 1/sqrt((a[x]+b[x]-c[x])*d[x]/e[x]);
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
代码在 Ubuntu 14.04.3 x86_64 中使用 g++ 4.8.4 编译: g++ -mavx avx.cpp -masm=intel -c -g -Wa,-ahl=avx.asm -Ofast
汇编源代码如下:
90 .LVL10:
91 006b C5FC2825 vmovaps ymm4, YMMWORD PTR .LC0[rip]
91 00000000
92 0073 31C0 xor eax, …Run Code Online (Sandbox Code Playgroud) 英特尔内在函数指南指出,内在函数_mm256_rsqrt_ps的相对误差最多为1.5*2^-12。但是,当我将 的结果_mm256_rsqrt_ps与平方根倒数 ( 1.0 / sqrt(x)) 的标准 C++ 计算结果进行比较时,我得到的相对误差远大于1.5*2^-12。
我使用以下程序来测试这一点:
#include <immintrin.h>
#include <iostream>
#include <math.h>
void test(float x) {
float resP = _mm256_cvtss_f32(_mm256_rsqrt_ps(_mm256_set1_ps(x)));
float res = 1.0 / sqrt(x);
float relErr = fabs(resP - res) / res;
std::cout << "x = " << x << std::endl;
std::cout << "resP = " << resP << std::endl;
std::cout << "res = " << res << std::endl;
std::cout << "relErr = …Run Code Online (Sandbox Code Playgroud) 我正在学习 SIMD 内在函数和并行计算。我不确定Intel对x86指令的定义sqrtpd是否 表示将同时计算传递给它的两个数字的平方根:
对源操作数(第二个操作数)中的两个、四个或八个压缩双精度浮点值的平方根执行 SIMD 计算,并将压缩双精度浮点结果存储在目标操作数(第二个操作数)中第一个操作数)。
我知道它明确表示SIMD 计算,但这是否意味着对于此操作,将同时计算两个数字的根?