我试图弄清楚在C中的某些代码中使用浮点数是否足够满足我的需求,但是在搜索之后并没有真正理解如何将精度转换为实际数字,我决定为我的测试用例写一点代码,看看结果如何。双性能比C漂浮快得多
漂浮看起来足够精确,但我非常惊讶,漂浮物在我的17 4700hq haswell处理器(windows 8.1 x64,C,MSVS v120)上运行时间延长了大约70%。我会预计运行时间会相似或浮动速度更快。但显然不是。所以我关掉了所有的优化,仍然是一样的。尝试在调试版本上,仍然是相同的性能问题。 AVX2和SSE 3都显示了这一点。
双打大概需要197秒的时间才能跑完并且漂浮343秒。我已经浏览了英特尔®64和IA-32架构软件开发人员手册,但考虑到它的规模和缺乏专业知识,我尚未从中收集有关此问题的任何答案。然后我看了看两者的拆卸情况,但我没有注意到我的未经训练的眼睛有明显的差异。
那么,有谁知道为什么会出现这种情况?这里是我用过的代码,除了anError变量之外,唯一的变化是从double到float。
#include <errno.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <time.h>
#include <sys/types.h>
#include <omp.h>
int main(void) {
clock_t start = clock() ;
// body of a candle
double open = 0.500000 ;
double close = 0.500001 ;
double end = 1 ;
uint64_t resultCounter = 0 ;
double anError = 0 ;
while (open < end){
while(close < end){
//calC# times result is postive. Should be 0.
double res = open - close ;
if (res > 0) {
resultCounter++ ;
if (anError < fabs(res)) { anError = res ; }
}
close = close + 0.000001 ;
}
open = open + 0.000001 ;
close = open + .000001 ;
}
clock_t finish = clock() ;
double duration = ((double) (finish - start))/CLOCKS_PER_SEC;
double iterations = (((end - .50000)/.000001) * ((end - .50000)/.000001)) ;
fprintf(stdout, "\nTotal processing time was %f seconds.\n", duration) ;
fprintf(stdout, "Error is %f. Number of times results were incorrect %llu out of %f iterations.\n",
anError, resultCounter, iterations) ;
return 0 ;
}
编辑:在数字的末尾缺乏f似乎是原因(感谢约阿希姆!)。显然,没有f后缀的float常量实际上是double! C的另一个怪癖,喜欢咬屁股的无知。不知道这种古怪背后的理由是什么,但耸耸肩。如果有人想写出一个好的答案,所以我可以接受它,感觉自由。
在使用'float'代替的程序中,是否记得使用例如'0.000001f'而不是简单的'0.000001'?或者使用['fabsf'](http://en.cppreference.com/w/c/numeric/math/fabs)而不是'fabs'?否则,编译器将不得不添加代码以在“float”和“double”之间转换数字。 –
此外,对于更公平的测试,您应该真正运行多次计算循环,并获得平均值。 –
嗯。如果在消除了隐式转换(使用f *()数学函数)后仍然存在任何差异,则结果将在很大程度上取决于编译器,CPU以及即使编译32位或64位。在具有SSE支持的x86上,SSE寄存器的宽度为128位,因此您可以通过任何方式进行转换。 8位硬件浮点寄存器(现在可能与SSE一起仿真)在80位宽,所以也没有“适合”。 – dhke