为了更好地理解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,情况必定会在不久前发生。
我认为事先检查每个部门远离"零成本"。你怎么看?我错过了一些明显的东西吗?
答案 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.已经指出的原因,不太可能以稳定的形式进入标准库。