这些之间有什么区别:
float foo1 = (int)(bar / 3.0);
float foo2 = floor(bar / 3.0);
Run Code Online (Sandbox Code Playgroud)
据我所知,两种情况都有相同的结果.编译代码有什么区别吗?
我已经了解到一些Intel/AMD CPU可以同时进行多次复用并添加SSE/AVX:
每个周期的FLOPS用于沙桥和haswell SSE2/AVX/AVX2.
我想知道如何在代码中做到最好,我也想知道它是如何在CPU内部完成的.我的意思是超标量架构.假设我想做一个很长的总和,如下面的SSE:
//sum = a1*b1 + a2*b2 + a3*b3 +... where a is a scalar and b is a SIMD vector (e.g. from matrix multiplication)
sum = _mm_set1_ps(0.0f);
a1 = _mm_set1_ps(a[0]);
b1 = _mm_load_ps(&b[0]);
sum = _mm_add_ps(sum, _mm_mul_ps(a1, b1));
a2 = _mm_set1_ps(a[1]);
b2 = _mm_load_ps(&b[4]);
sum = _mm_add_ps(sum, _mm_mul_ps(a2, b2));
a3 = _mm_set1_ps(a[2]);
b3 = _mm_load_ps(&b[8]);
sum = _mm_add_ps(sum, _mm_mul_ps(a3, b3));
...
Run Code Online (Sandbox Code Playgroud)
我的问题是如何将其转换为同时乘法并添加?数据可以依赖吗?我的意思是CPU可以_mm_add_ps(sum, _mm_mul_ps(a1, b1))同时执行还是在乘法中使用的寄存器和add必须是独立的?
最后,这如何适用于FMA(与Haswell)?是_mm_add_ps(sum, _mm_mul_ps(a1, b1))自动转换为单个FMA指令还是微操作?
例如,这篇博客说0.005并不完全是0.005,但是舍入这个数字会产生正确的结果.
我在C++中尝试了各种舍入,但在将数字舍入到某些小数位时失败了.例如,Round(x,y)将x舍入为y的倍数.所以回合(37.785,0.01)应该给你37.79而不是37.78.
我正在重新打开这个问题,向社区寻求帮助.问题在于浮点数的不精确性(37,785表示为37.78499999999).
问题是Excel如何解决这个问题?
我对libc的"sin"功能有疑问.
#include <cmath>
#include <stdio.h>
int main(int argc, char **argv)
{
double tt = 6.28318530717958620000; // 2 * M_PI
double yy = ::sin(tt);
printf("%.32f\n", yy);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
当使用"g ++"编译上述代码而没有任何优化选项时,它将输出"-0.00000000000000024492127076447545".但如果使用"-O3"选项,则输出"-0.00000000000000024492935982947064".
为什么不在没有"-O3"的情况下返回"-0.00000000000000024492935982947064"?提前致谢.
c++当使用-O0或编译时,以下程序给出的数值不同-O1。
#include <iostream>
#include <array>
#include <cmath>
#include <iomanip>
int main()
{
std::array<double, 2> v;
v.fill(0);
std::get<0>(v) = 0x1.5b4d3afe1f7d2p-1;
double theta = 0x1.1aef12f82caf9p+2;
double c = std::cos(theta);
double s = std::sin(theta);
double vi = c * std::get<0>(v) - s * std::get<1>(v);
double vj = s * std::get<0>(v) + c * std::get<1>(v);
std::get<0>(v) = vi;
std::get<1>(v) = vj;
std::cout << std::hexfloat;
for (const auto& x : v)
std::cout << x << " ";
std::cout << std::endl; …Run Code Online (Sandbox Code Playgroud) 看看这个程序:
#include <iostream>
#include <cmath>
using namespace std;
typedef pair<int, int> coords;
double dist(coords a, coords b)
{
return sqrt((a.first - b.first) * (a.first - b.first) +
(a.second - b.second) * (a.second - b.second));
}
int main()
{
coords A = make_pair(1, 0);
coords B = make_pair(0, 1);
coords C = make_pair(-1, 0);
coords D = make_pair(0, -1);
cerr.precision(20);
cerr << dist(A, B) + dist(C, D) << endl;
cerr << dist(A, D) + dist(B, C) << endl;
if(dist(A, B) + …Run Code Online (Sandbox Code Playgroud) 我目前正在阅读优秀的双双和四双算术库,在前几行我注意到他们通过以下方式执行求和:
std::pair<double, double> TwoSum(double a, double b)
{
double s = a + b;
double v = s - a;
double e = (a - (s - v)) + (b - v);
return std::make_pair(s, e);
}
Run Code Online (Sandbox Code Playgroud)
误差的计算e依赖于计算遵循该操作顺序的事实,因为IEEE-754浮点数学的非关联属性.
如果我在现代优化C++编译器(例如MSVC或gcc)中编译它,我可以确保编译器不会优化计算的方式吗?
其次,这在C++标准中是否可以保证?
我有MinGW GCC 4.8.1和以下代码:
#include <iostream>
#include <cmath>
double eval(int a, int b){
return std::sqrt(a) + std::sqrt(b);
}
int main(){
double first = eval(545, 331);
double second = eval(545, 331);
if(first < second)
std::cout << "first < second" << std::endl;
if(first == second)
std::cout << "first == second" << std::endl;
if(first > second)
std::cout << "first > second" << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
如果编译-O0,程序打印预期的结果:
first == second
Run Code Online (Sandbox Code Playgroud)
但是,如果使用-O1,-O2或编译-O3程序打印:(结果在ideone上)
first < second
first == …Run Code Online (Sandbox Code Playgroud) 我一直在创建一个用于实施 Eratosthenes 筛分的简短程序。在他的程序中,我使用 int startingPointwhich 保存了当前素数的值,它的乘法被标记为非素数,从它的平方开始。我使用 pow() 函数计算当前循环中起点的平方。这样做的时候,我遇到了一个奇怪的现象。当startingPoint等于 时5,则后int i = pow(startingPoint,2)的值为i24,而不是 25。这种现象仅在startingPoint等于 5时发生。之后,我运行了一些测试,导致以下代码片段:
#include <iostream>
#include <math.h>
int main()
{
int p=5;
int num1 = pow(5,2);
int num2 = pow(p,2);
float num3 = pow(p,2);
int num4 = floor(pow(p,2));
std::cout.precision(10);
std::cout<<num1<<std::endl; //25
std::cout<<num2<<std::endl; //24
std::cout<<std::fixed<<num3<<std::endl; //25.0000000000
std::cout<<num4<<std::endl; //25
}
Run Code Online (Sandbox Code Playgroud)
可以看出,如果我pow用int文字调用,结果将是数字的实际平方。但是,如果我使用 using 调用它int p=5,那么pow返回的结果实际上比预期的结果低一个。如果我将结果传递给一个float变量,它也会收到正确的结果。
现在,我知道pow计算幂的方法是通过近似计算,因此,在转换为整数时可能会出现诸如此类的错误。我可能就让它这样吧。但真正让我停下来思考的是num4. pow(p,2) …
我有一个小函数,它应该根据机器学习算法进行预测.该函数无法正常工作,因此我将一个print语句放入检查值,突然间它开始工作了.当我注释掉打印行时,它会再次停止工作.有什么我不知道为什么会发生这种情况?
int makePrediction( const InstanceT & instance, bool biased ){
double dotProduct = ( biased ? instance * _weights + _bias : instance * _weights );
std::cout << "dotProduct = " << dotProduct << std::endl;
return ( dotProduct > 0 ? 1 : -1 );
}
Run Code Online (Sandbox Code Playgroud)
由于某种原因产生了不同的结果
int makePrediction( const InstanceT & instance, bool biased ){
double dotProduct = ( biased ? instance * _weights + _bias : instance * _weights );
return ( dotProduct > 0 ? 1 : …Run Code Online (Sandbox Code Playgroud) 这是一个普遍的问题,但由于我主要处理gcc/g ++/VStudio,我将其标记为c/c ++.当我搞乱优化选项时,我想到了这个问题.在最简单的形式中,考虑算术运算,如i / 6 * 8.如果一个人面对这个表达,他很可能将它简化为类似的东西i / 3 * 4.如果他更习惯乘以4,他将首先这样做,即(i * 4) / 3.我必须再次强调,这只是一个简单的例子.
那么编译器呢?他们是否有可能对此类操作采取相同措施?而且既然我们知道在上面的例子中,如果i是一个整数,那么简化和改变操作的顺序可能会导致完全不同的结果,问题可以改为:编译器是否完全避免了这样的动作?
如果我们希望程序完全按照我们的说法进行一些算术运算而不改变运算顺序,那么我们是否应该担心编译器的行为?