正如标题所示.我需要做这样的大量计算:
re = (x^a + y^a + z^a)^(1/a).
Run Code Online (Sandbox Code Playgroud)
其中{ x,y,z }> = 0.更具体地,a是正浮点常数,x,y,z是浮点数.这^
是一个取幂运算符.
目前,我不想使用SIMD,但希望有其他一些技巧来加速它.
static void heavy_load(void) {
static struct xyz_t {
float x,y,z;
};
struct xyz_t xyzs[10000];
float re[10000] = {.0f};
const float a = 0.2;
/* here fill xyzs using some random positive floating point values */
for (i = 0; i < 10000; ++ i) {
/* here is what we need to …
Run Code Online (Sandbox Code Playgroud) 关于sin
用表格计算基本函数的文献参考公式:
sin(x) = sin(Cn) * cos(h) + cos(Cn) * sin(h)
Run Code Online (Sandbox Code Playgroud)
其中x = Cn + h
,Cn
是针对其恒定sin(Cn)
和cos(Cn)
已被预先计算并在表中可用的,并且,如果以下半乳糖的方法,Cn
已被选择为使得两个sin(Cn)
和cos(Cn)
密切由浮点数近似.数量h
接近0.0
.此公式的参考示例是本文(第7页).
我不明白为什么这是有道理的:cos(h)
然而,它被计算,对于某些值,至少0.5 ULP可能是错误的h
,并且因为它接近1.0
,这似乎对结果的准确性有极大的影响.sin(x)
以这种方式计算.
我不明白为什么不使用下面的公式:
sin(x) = sin(Cn) + (sin(Cn) * (cos(h) - 1.0) + cos(Cn) * sin(h))
Run Code Online (Sandbox Code Playgroud)
然后两个量(cos(h) - 1.0)
,并sin(h)
可以用,很容易做出准确的,因为它们产生接近零的结果多项式来近似.为价值观sin(Cn) * (cos(h) - 1.0)
, cos(Cn) * sin(h)
并为他们的总和仍然很小,其绝对精度,该总和表示,因此,加入这个量的少量ULPS表达sin(Cn)
几乎是正确舍入. …
GCC的手册页指出-funsafe-math-optimizations
允许优化"(a)假设参数和结果有效,(b)可能违反IEEE或ANSI标准",但这不是很精确,是吗?
在这种情况下,什么可能是"无效"的论点?NaN的?Infinites?次归?负数到sqrt()
?
结果允许偏离IEEE或ANSI标准多远?它是"仅仅"像操作关联性和排序的东西,还是可能包括例如.与NaN的真实比较或与无限的不正确比较?可以存储变量进行重新四舍五入已被使用后(使得对变量 x
和y
,(x == y) + (x == y)
可以评估到1)?可以isinf()
/ isnan()
停止工作吗?
GCC开发人员是否遵循任何特定的系统或纪律来解决这些问题,或者答案在不同版本之间是否会有很大不同?
与朋友的讨论导致以下实现:
>>> import dis
>>> i = lambda n: n*24*60*60
>>> dis.dis(i)
1 0 LOAD_FAST 0 (n)
3 LOAD_CONST 1 (24)
6 BINARY_MULTIPLY
7 LOAD_CONST 2 (60)
10 BINARY_MULTIPLY
11 LOAD_CONST 2 (60)
14 BINARY_MULTIPLY
15 RETURN_VALUE
>>> k = lambda n: 24*60*60*n
>>> dis.dis(k)
1 0 LOAD_CONST 4 (86400)
3 LOAD_FAST 0 (n)
6 BINARY_MULTIPLY
7 RETURN_VALUE
Run Code Online (Sandbox Code Playgroud)
仅通过减少指令数量,第二个例子显然更有效.
我的问题是,这个优化是否有一个名称,为什么不在第一个例子中发生?
另外,我不确定这是否重复为什么GCC没有优化a*a*a*a*a*a到(a*a*a)*(a*a*a)?; 如果是,请进一步解释,因为它适用于Python.
好吧,我一直在和一位朋友谈论编译器和程序的优化,他建议这样n * 0.5
做比n / 2
.我说编译器会自动执行这种优化,所以我编写了一个小程序来查看n / 2
和之间是否存在差异n * 0.5
:
师:
#include <stdio.h>
#include <time.h>
int main(int argc, const char * argv[]) {
int i, m;
float n, s;
clock_t t;
m = 1000000000;
t = clock();
for(i = 0; i < m; i++) {
n = i / 2;
}
s = (float)(clock() - t) / CLOCKS_PER_SEC;
printf("n = i / 2: %d calculations took %f seconds (last calculation = %f)\n", m, …
Run Code Online (Sandbox Code Playgroud) 我这个问题已经很久了,但是却不知道在哪里看。如果某个操作多次编写,编译器会简化它还是运行完全相同的操作并获得完全相同的答案?
例如,在下文(i%3)*10
中,多次重复类似c的伪代码。
for(int i=0; i<100; i++) {
array[(i%3)*10] = someFunction((i%3)*10);
int otherVar = (i%3)*10 + array[(i%3)*10];
int lastVar = (i%3)*10 - otherVar;
anotherFunction(lastVar);
}
Run Code Online (Sandbox Code Playgroud)
我了解变量在视觉上会更好,但会更快吗?是(i%3)*10
计算每循环5次?
在某些情况下,我不知道使用变量还是仅保留原始操作更快。
编辑:在胜利10上使用gcc(MinGW.org GCC-8.2.0-3)8.2.0
下面声明norm
的C++ vector
类中的成员函数标记为const
和(据我所知)不包含任何副作用.
template <unsigned int N>
struct vector {
double v[N];
double norm() const {
double ret = 0;
for (int i=0; i<N; ++i) {
ret += v[i]*v[i];
}
return ret;
}
};
double test(const vector<100>& x) {
return x.norm() + x.norm();
}
Run Code Online (Sandbox Code Playgroud)
如果我打电话norm
多次上const
的实例vector
(见test
上面的函数)与GCC编译器(5.4版本)和优化开启(即-O3
),那么编译器内联norm
,但仍计算的结果norm
多次,即使结果不应该改变.为什么编译器不优化第二次调用norm
而只计算一次这个结果?这个答案似乎表明,如果编译器确定该norm
函数没有任何副作用,编译器应该执行此优化.为什么在这种情况下不会发生这种情况?
请注意,我正在使用Compiler Explorer确定编译器生成的内容,并且下面给出了gcc版本5.4的程序集输出.clang编译器给出了类似的结果.另请注意,如果我使用gcc的编译器属性手动标记norm
为使用const函数__attribute__((const))
,那么第二次调用会根据需要进行优化,但我的问题是为什么gcc(和clang)不会自动执行此操作,因为norm
定义可用?
test(vector<100u>&): …
Run Code Online (Sandbox Code Playgroud) 我的老师声称处理器有时可以并行进行FPU操作.像这样:
float a = 3.14;
float b = 5.12;
float c;
float d = 3.02;
float e = 2.52;
float f;
c = a + b;
f = e + d;
Run Code Online (Sandbox Code Playgroud)
所以,正如我所听到的,上面的2个添加操作将比以下更快地执行:
float a = 3.14;
float b = 5.12;
float c;
float d = 3.02;
float e = 2.52;
float f;
c = a + b;
f = c + d;
Run Code Online (Sandbox Code Playgroud)
因为处理器必须等到c
计算完成
我想验证这一点,所以我编写了一个执行第二件操作的函数,它通过检查时间戳计数器来测量时间:
flds h # st(7)
flds g # st(6)
flds f # st(5)
flds e …
Run Code Online (Sandbox Code Playgroud) 类似于问题gcc的ffast-math实际上做了什么?并且与Clang优化级别的SO问题有关,我想知道在实际条件下优化是做什么clang
的-Ofast
,以及它们是否与gcc完全不同,或者这是否依赖于编译器依赖于硬件.
根据clang优化级别的公认答案,-Ofast
增加了-O3
优化:-fno-signed-zeros -freciprocal-math -ffp-contract=fast -menable-unsafe-fp-math -menable-no-nans -menable-no-infs
.这似乎完全与浮点数学相关.但是这些优化对于像C++这样的事物来说意味着什么呢?像英特尔酷睿i7这样的CPU上的浮点数通用数学函数以及这些差异有多可靠?
例如,实际上:
该代码std::isnan(std::numeric_limits<float>::infinity() * 0)
返回真正的我-O3
.我相信这是符合IEEE数学标准的结果.
随着-Ofast
不过,我得到一个错误的返回值.此外,该操作(std::numeric_limits<float>::infinity() * 0) == 0.0f
返回true.
我不知道这是否与gcc中看到的相同.我不清楚结果如何依赖于结构,也不清楚编译器如何依赖它们,也不清楚是否存在任何适用的标准-Ofast
.
如果有人可能会产生类似于一组单元测试或代码公案来解决这个问题,那可能是理想的.我已经开始做这样的事情,但宁愿不重新发明轮子.
进行乘法比在c ++中提高功率2更有效吗?
我正在尝试做最后的详细优化.编译器会将x*x与pow(x,2)相同吗?如果我没记错的话,乘法因某种原因更好,但也许在c ++ 11中并不重要.
谢谢