每次分裂发生时,我都可以禁用零分割检查吗?

时间:2017-03-02 00:05:00

标签: performance exception rust divide-by-zero

为了更好地理解Rusts恐慌/异常机制,我编写了以下代码:

public class MapFragment extends SupportMapFragment implements OnMapReadyCallback {

    private GoogleMap mGoogleMap;

    @Override
    public void onResume() {
        super.onResume();
        if (mGoogleMap == null) {
            getMapAsync(this);
        }
    }

    @Override
    public void onMapReady(GoogleMap googleMap) {
        mGoogleMap = googleMap;
        // latitude and longitude
        double latitude = 17.385044;
        double longitude = 78.486671;

        // create marker
        MarkerOptions marker = new MarkerOptions().position(
                new LatLng(latitude, longitude)).title("Hello Maps");

        // Changing marker icon
        marker.icon(BitmapDescriptorFactory
                .defaultMarker(BitmapDescriptorFactory.HUE_ROSE));

        // adding marker
        googleMap.addMarker(marker);
        CameraPosition cameraPosition = new CameraPosition.Builder()
                .target(new LatLng(17.385044, 78.486671)).zoom(12).build();
        googleMap.animateCamera(CameraUpdateFactory
                .newCameraPosition(cameraPosition));
    }
}

我想检查Rust如何处理除零案件。最初我认为它要么是采取未处理的SIGFPE面对死亡,要么实施处理程序并将其重新路由到恐慌(现在可以处理?)。

代码很冗长,因为我想确保Rust不做任何事情" smart"当它在编译时知道某事为零时,因此用户输入。只要给它一个' A'它应该成功。

我发现Rust实际上产生的代码每次在除法发生之前检查零除法。我甚至看了一次装配。 : - )

长话短说:我可以禁用此行为吗?我想对于较大的数据集,这可能会产生很大的性能影响。为什么不使用我们的CPU能力为我们检测这些东西?我可以设置自己的信号处理程序并处理SIGFPE吗?

根据an issue on Github,情况必定会在不久前发生。

我认为事先检查每个部门远离"零成本"。你怎么看?我错过了一些明显的东西吗?

2 个答案:

答案 0 :(得分:7)

  

我认为事先检查每个部门远离"零成本"。你觉得怎么样?

你测量了什么?

执行的指令数量很少代表性能;矢量化代码通常更冗长,但速度更快。

所以真正的问题是:这个分支的成本是多少?

由于故意除以0是不太可能的,并且意外地进行这种情况的可能性稍微大一些,因此当除数为0时,除了之外,总是会正确预测分支。但是,考虑到恐慌的代价,错误预测的分支是您最不担心的。

因此,费用是:

  • 稍微胖一点的装配,
  • 分支预测器中的占用插槽。

确切的影响难以取得资格,对于数学繁重的代码,它可能会产生影响。虽然我会提醒你一个整数除法是〜100个循环 1 开始,所以数学繁重的代码会尽可能地避开它(它可能是最单一的时间)消耗CPU中的指令。)

1 请参阅Agner Fog's Instruction Table:例如,在Intel Nehalem DIV上,IDIV在64位积分上的延迟分别为28到90个周期和37到100个周期。 / em>的

除此之外,rustc在LLVM之上实现,它委托实际的代码生成。因此,在许多情况下,rustc受LLVM的支配,这就是其中之一。

LLVM有两个整数除法指令:udiv and sdiv

两者都有未定义的行为,除数为0.

Rust旨在消除未定义的行为,因此具有以防止除以0,以免优化器将发出的代码破坏而无法修复。

它使用LLVM手册中建议的检查。

答案 1 :(得分:2)

  

长话短说:我可以禁用此行为吗?

是的,您可以:std::intrinsics::unchecked_div(a, b)。 您的问题也适用于余数(这就是Rust调用modulo的方式):std::intrinsics::unchecked_rem(a, b)。 我检查了汇编输出here,将其与C ++进行比较。

在文档中指出:

  

这是一个仅限夜间的实验性API。 (core_intrinsics)

     

内部技术不太可能被稳定,相反,应该通过标准库其余部分中的稳定接口来使用它们

因此,您必须使用夜间版本,并且由于Matthieu M.已经指出的原因,不太可能以稳定的形式进入标准库。