相关疑难解决方法(0)

编译32位和64位时,性能差异很大(快26倍)

我试图衡量在访问值类型和引用类型列表时使用a for和a 的区别foreach.

我使用以下类进行分析.

public static class Benchmarker
{
    public static void Profile(string description, int iterations, Action func)
    {
        Console.Write(description);

        // Warm up
        func();

        Stopwatch watch = new Stopwatch();

        // Clean up
        GC.Collect();
        GC.WaitForPendingFinalizers();
        GC.Collect();

        watch.Start();
        for (int i = 0; i < iterations; i++)
        {
            func();
        }
        watch.Stop();

        Console.WriteLine(" average time: {0} ms", watch.Elapsed.TotalMilliseconds / iterations);
    }
}
Run Code Online (Sandbox Code Playgroud)

我用double我的价值类型.我创建了这个'假类'来测试引用类型:

class DoubleWrapper
{
    public double Value { get; set; }

    public DoubleWrapper(double value)
    {
        Value …
Run Code Online (Sandbox Code Playgroud)

c# performance 32bit-64bit

78
推荐指数
2
解决办法
6303
查看次数

根据平台,C#舍入不同?

我有这么小的代码

double s = -2.6114289999999998;
double s7 = Math.Round(s, 7);
double s5 = Math.Round(s, 5);
double s6 = Math.Round(s, 6);
Run Code Online (Sandbox Code Playgroud)

有了Platform = Any CPU,我明白了

s7: -2.611429   
s5: -2.61143    
s6: -2.611429   
Run Code Online (Sandbox Code Playgroud)

使用Platform = x64,我得到了

s7: -2.6114289999999998 
s5: -2.61143    
s6: -2.6114289999999998
Run Code Online (Sandbox Code Playgroud)

为什么?(从VS的Locals窗口复制的输出)


整段代码是:

    private void btnAlign_Click(object sender, EventArgs e)
    {
        double s = -2.6114289999999998;
        double s7 = Math.Round(s, 7);
        double s5 = Math.Round(s, 5);
        double s6 = Math.Round(s, 6);
    }
Run Code Online (Sandbox Code Playgroud)

c# rounding

17
推荐指数
1
解决办法
1067
查看次数

为什么Math.Exp在32位和64位之间给出不同的结果,具有相同的输入,相同的硬件

我使用.NET 2.0与PlatformTarget x64和x86.我给Math.Exp输入相同的输入数,并且它在任一平台上都返回不同的结果.

MSDN说你不能依赖文字/解析的Double来代表平台之间的相同数字,但我认为我在下面使用Int64BitsToDouble可以避免这个问题,并保证在两个平台上输入相同的Math.Exp.

我的问题是为什么结果不同?我原以为:

  • 输入以相同的方式存储(双/ 64位精度)
  • 无论处理器的位数如何,FPU都会进行相同的计算
  • 输出以相同的方式存储

我知道我不应该比较15/17位数后的浮点数,但我对这里的不一致感到困惑,看起来在同一硬件上看起来是相同的操作.

任何人都知道引擎盖下发生了什么?

double d = BitConverter.Int64BitsToDouble(-4648784593573222648L); // same as Double.Parse("-0.0068846153846153849") but with no concern about losing digits in conversion
Debug.Assert(d.ToString("G17") == "-0.0068846153846153849"
    && BitConverter.DoubleToInt64Bits(d) == -4648784593573222648L); // true on both 32 & 64 bit

double exp = Math.Exp(d);

Console.WriteLine("{0:G17} = {1}", exp, BitConverter.DoubleToInt64Bits(exp));
// 64-bit: 0.99313902928727449 = 4607120620669726947
// 32-bit: 0.9931390292872746  = 4607120620669726948
Run Code Online (Sandbox Code Playgroud)

在打开或关闭JIT的两个平台上,结果都是一致的.

[编辑]

我对下面的答案并不完全满意,所以这里有一些我搜索的细节.

http://www.manicai.net/comp/debugging/fpudiff/说:

因此32位使用80位FPU寄存器,64位使用128位SSE寄存器.

CLI标准表示,如果硬件支持双精度,则可以用更高的精度表示双精度:

[原理:此设计允许CLI为浮点数选择特定于平台的高性能表示,直到它们被放置在存储位置.例如,它可能能够在硬件寄存器中保留浮点变量,这些变量提供的精度比用户请求的更高.在分区I 69同时,CIL生成器可以通过使用转换指令强制操作遵守特定于语言的表示规则.最终理由]

http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-335.pdf(12.1.3处理浮点数据类型)

我认为这就是这里发生的事情,因为Double的标准15位精度后结果不同.64位Math.Exp结果更精确(它有一个额外的数字)因为内部64位.NET使用的FPU寄存器比32位.NET使用的FPU寄存器更精确.

.net c# math x86-64 32bit-64bit

11
推荐指数
1
解决办法
2064
查看次数

将float浮动到int,32位C的区别

我目前正在使用需要运行32位系统的旧代码.在这项工作中,我偶然发现了一个问题(出于学术兴趣),我想了解其原因.

如果对变量或表达式进行强制转换,似乎在32位C中从float转换为int的行为会有所不同.考虑该计划:

#include <stdio.h>
int main() {
   int i,c1,c2;
   float f1,f10;
   for (i=0; i< 21; i++)  {
      f1 = 3+i*0.1;
      f10 = f1*10.0;
      c1 = (int)f10;
      c2 = (int)(f1*10.0);
      printf("%d, %d, %d, %11.9f, %11.9f\n",c1,c2,c1-c2,f10,f1*10.0);
   }
}
Run Code Online (Sandbox Code Playgroud)

使用-m32修饰符直接在32位系统或64位系统上编译(使用gcc),程序的输出为:

30, 30, 0, 30.000000000 30.000000000
31, 30, 1, 31.000000000 30.999999046
32, 32, 0, 32.000000000 32.000000477
33, 32, 1, 33.000000000 32.999999523
34, 34, 0, 34.000000000 34.000000954
35, 35, 0, 35.000000000 35.000000000
36, 35, 1, 36.000000000 35.999999046
37, 37, 0, 37.000000000 37.000000477
38, …
Run Code Online (Sandbox Code Playgroud)

c casting 32-bit

11
推荐指数
2
解决办法
813
查看次数

128位到512位寄存器用于什么?

在查看x86/x64架构中的寄存器表之后,我注意到有128,256和512位寄存器的整个部分,我从未见过它们用于汇编或反编译的C/C++代码: XMM(0-15)表示128,YMM(0-15)表示256,ZMM(0-31)512.

做了一些挖后我所收集的是,你必须使用2个64位操作,以一个128位的数字进行的,而不是使用通用的数学,add,sub,mul,div操作.如果是这种情况,那么具有这些扩展寄存器集的用途究竟是什么,是否有任何汇编操作可以用来操作它们?

assembly sse x86-64 simd cpu-registers

7
推荐指数
1
解决办法
645
查看次数

std :: pow在32位和64位应用程序中产生不同的结果

我发现一些复杂计算的结果不匹配.当我彻底观察到中间结果时,它的std :: pow函数会产生不匹配.以下是输入/输出.

long double dvalue = 2.7182818284589998;
long double dexp = -0.21074699576017999;
long double result = std::powl( dvalue, dexp); 
Run Code Online (Sandbox Code Playgroud)

64位 - >结果= 0.80997896907296496和32位 - >结果= 0.80997896907296507

我正在使用VS2008.我已尝试过其他功能的pow功能,需要很长的双倍并返回长双,但仍然看到相同的差异.

double pow( double base, double exponent );

long double powl( long double base, long double exponent );

我已经阅读了一些关于此的信息:

Intel x86处理器内部使用80位扩展精度,而double通常是64位宽.不同的优化级别会影响来自CPU的浮点值保存到内存中的频率,从而将80位精度舍入为64位精度.或者,使用long double类型,通常在gcc上为80位宽,以避免从80位到64位精度的舍入.

有人能让我清楚地了解差异和克服这种差异的方法.

c++ x86-64 c++11

6
推荐指数
2
解决办法
1461
查看次数

比较双重时的不同行为

您好我知道计算机受数字精度的限制,有些数字无法在二进制系统中准确表示.这就是我问为什么这样比较的原因

(0.1*3) == 0.3
Run Code Online (Sandbox Code Playgroud)

在Java语言中评估为false在C中它评估为true,对我来说Java行为更直观一些.任何提供的答案都不能回答我的问题,为什么他们有不同的行为,因为两者都使用IEEE 754标准.

@update我正在使用ideone来测试条件.

c java

6
推荐指数
1
解决办法
114
查看次数

在任何基于x86的体系结构中,是否有浮点密集型代码会产生位精确的结果?

我想知道在C或C ++中使用浮点运算的任何代码在任何基于x86的体系结构中是否都会产生精确的结果,而不管代码的复杂性如何。

据我所知,自从Intel 8087开始,任何x86架构都使用了准备处理IEEE-754浮点数的FPU单元,而且我看不出任何原因导致不同架构的结果不同。但是,如果它们不同(即由于不同的编译器或不同的优化级别),那么是否有某种方法可以通过仅配置编译器来产生位精确结果?

c x86 ieee-754 fast-math

5
推荐指数
1
解决办法
824
查看次数

32/64位设备上的Objective-C划分产生不同的结果

如标题中所述,当我尝试执行以下divsion时,我会得到两个不同的结果,具体取决于设备的体系结构:

unsigned int a = 42033;
unsigned int b = 360;
unsigned int c = 466
double result = a / (double)(b * c);
// on arm64 -> result = 0.25055436337625181
// on armv7 -> result = 0.24986030696800732
Run Code Online (Sandbox Code Playgroud)

为什么结果不匹配?

根据针对Cocoa Touch的 Apple 64位过渡指南,这些数据类型在32位和64位运行时具有相同的大小.

编辑

完整的代码:

#import "UIImage+MyCategory.h"

#define CLIP_THRESHOLD 0.74 // if this much of the image is the clip color, leave it alone

typedef struct {
    unsigned int leftNonColorIndex;
    unsigned int rightNonColorIndex;
    unsigned int nonColorCount;
} scanLineResult; …
Run Code Online (Sandbox Code Playgroud)

c math arm objective-c ios

5
推荐指数
1
解决办法
440
查看次数

不相关的代码会更改计算结果

我们有一些代码会在某些机器上产生意外结果.我把它缩小到一个简单的例子.在下面的linqpad片段中,方法GetValGetVal2实现基本相同,尽管前者还包括对NaN的检查.但是,每个返回的结果都不同(至少在我的机器上).

void Main()
{
    var x = Double.MinValue;
    var y = Double.MaxValue;
    var diff = y/10 - x/10;

    Console.WriteLine(GetVal(x,6,diff));
    Console.WriteLine(GetVal2(x,6,diff));
}

public static double GetVal(double start, int numSteps, double step)
{
    var res = start + numSteps * step;
    if (res == Double.NaN)
        throw new InvalidOperationException();
    return res;
}

public static double GetVal2(double start, int numSteps, double step)
{
    return start + numSteps * step;
}
Run Code Online (Sandbox Code Playgroud)

结果

3.59538626972463E+307
Infinity
Run Code Online (Sandbox Code Playgroud)

为什么会发生这种情况,是否有一种避免它的简单方法?与寄存器有关?

c# floating-point cpu-registers

5
推荐指数
1
解决办法
110
查看次数

boost :: random :: uniform_real_distribution应该是跨处理器的相同吗?

以下代码在x86 32位与64位处理器上产生不同的输出.

应该这样吗?如果我用std :: uniform_real_distribution替换它并使用-std = c ++ 11编译它会在两个处理器上产生相同的输出.

#include <iostream>
#include <boost/random/mersenne_twister.hpp>
#include <boost/random/uniform_real_distribution.hpp>

int main()
{
    boost::mt19937 gen;
    gen.seed(4294653137UL);
    std::cout.precision(1000);
    double lo = - std::numeric_limits<double>::max() / 2 ;
    double hi = + std::numeric_limits<double>::max() / 2 ;
    boost::random::uniform_real_distribution<double> boost_distrib(lo, hi);
    std::cout << "lo " << lo << '\n';
    std::cout << "hi " << hi << "\n\n";
    std::cout << "boost distrib gen " << boost_distrib(gen) << '\n';
}
Run Code Online (Sandbox Code Playgroud)

c++ random x86 boost

3
推荐指数
1
解决办法
688
查看次数

为什么输出不同,公式如何相同?

int y = 89;
int foo =  (y / 10.0 - y / 10) * 10;
int bar = (89 / 10.0 - 89 / 10) * 10;
cout << foo << ' ' << bar << '\n';
Run Code Online (Sandbox Code Playgroud)

上面的代码是想得到一个整数y的最后一位,奇怪的是foo is8和bar is 9,为什么会这样呢?两个版本的表达式有什么区别?

c++ floating-point

2
推荐指数
1
解决办法
61
查看次数