我有3个非常大的有符号整数.
long x = long.MaxValue;
long y = long.MaxValue - 1;
long z = long.MaxValue - 2;
Run Code Online (Sandbox Code Playgroud)
我想计算他们的截断平均值.预期的平均值是long.MaxValue - 1,即9223372036854775806.
无法将其计算为:
long avg = (x + y + z) / 3; // 3074457345618258600
Run Code Online (Sandbox Code Playgroud)
注意:我阅读了有关2个数字的平均值的所有问题,但我不知道该技术如何应用于平均3个数字.
使用它会很容易BigInteger,但我们假设我不能使用它.
BigInteger bx = new BigInteger(x);
BigInteger by = new BigInteger(y);
BigInteger bz = new BigInteger(z);
BigInteger bavg = (bx + by + bz) / 3; // 9223372036854775806
Run Code Online (Sandbox Code Playgroud)
如果我转换为double,那么,当然,我失去了精度:
double dx = x;
double dy = y;
double …Run Code Online (Sandbox Code Playgroud) 我一直看到人们声称MOV指令可以在x86中免费,因为寄存器重命名.
对于我的生活,我无法在一个测试用例中验证这一点.每个测试用例我尝试揭穿它.
例如,这是我用Visual C++编译的代码:
#include <limits.h>
#include <stdio.h>
#include <time.h>
int main(void)
{
unsigned int k, l, j;
clock_t tstart = clock();
for (k = 0, j = 0, l = 0; j < UINT_MAX; ++j)
{
++k;
k = j; // <-- comment out this line to remove the MOV instruction
l += j;
}
fprintf(stderr, "%d ms\n", (int)((clock() - tstart) * 1000 / CLOCKS_PER_SEC));
fflush(stderr);
return (int)(k + j + l);
}
Run Code Online (Sandbox Code Playgroud)
这为循环生成以下汇编代码(随意生成这个你想要的;你显然不需要Visual C++):
LOOP:
add edi,esi
mov …Run Code Online (Sandbox Code Playgroud) 我最近遇到了这个辉煌的cpp2015演讲CppCon 2015:Chandler Carruth"调优C++:基准测试,CPU和编译器!哦,我的!"
提到的阻止编译器优化代码的技术之一是使用以下函数.
static void escape(void *p) {
asm volatile("" : : "g"(p) : "memory");
}
static void clobber() {
asm volatile("" : : : "memory");
}
void benchmark()
{
vector<int> v;
v.reserve(1);
escape(v.data());
v.push_back(10);
clobber()
}
Run Code Online (Sandbox Code Playgroud)
我试图理解这一点.问题如下.
1)越过clobber逃脱的好处是什么?
2)从上面的例子看起来,clobber()可以防止先前的语句(push_back)被优化.如果是这样的话,为什么下面的代码片段不正确?
void benchmark()
{
vector<int> v;
v.reserve(1);
v.push_back(10);
clobber()
}
Run Code Online (Sandbox Code Playgroud)
如果这不够混乱,那么愚蠢(FB的线程化lib)就会有一个更奇怪的实现
相关片段:
template <class T>
void doNotOptimizeAway(T&& datum) {
asm volatile("" : "+r" (datum));
}
Run Code Online (Sandbox Code Playgroud)
我的理解是上面的片段通知编译器程序集块将写入数据.但是如果编译器发现没有这个数据的消费者,它仍然可以优化生成数据的实体吗?
我认为这不是常识,任何帮助表示赞赏!