Rust: 浮動小数点から敎数ぞのキャストは、未定矩の動䜜を匕き起こす可胜性がありたす

䜜成日 2013幎10月31日  Â·  234コメント  Â·  ゜ヌス: rust-lang/rust

2020幎4月18日珟圚の状況

asのsaturating-float-casts動䜜を安定させ、以前の動䜜を凊理する安党でないラむブラリ関数を安定させる予定です。 その安定化プロセスに関する最新の議論に぀いおは、71269を参照しおください。

2018-11-05珟圚のステヌタス

コンパむラにフラグ-Zsaturating-float-castsが実装されたした。これにより、すべおの浮動小数点から敎数ぞのキャストが「飜和」動䜜になり、範囲倖の堎合は最も近い範囲にクランプされたす。 この倉曎のベンチマヌクの、䞀郚のプロゞェクトでは

次のステップは、これらのケヌスのパフォヌマンスを回埩する方法を理解するこずです。

  • 1぀のオプションは、今日のasキャスト動䜜堎合によっおはUBを䜿甚しお、関連するタむプなどにunsafe関数を远加するこずです。
  • もう1぀は、LLVMがfreeze抂念を远加するのを埅぀こずです。これは、ガベヌゞビットパタヌンを取埗するこずを意味したすが、少なくずもUBではありたせん。
  • もう1぀は、珟圚のcodegenが倧幅に最適化されおいないため、LLVMIRでむンラむンアセンブリを介しおキャストを実装するこずです。

叀いステヌタス

曎新@nikomatsakisによる倚くの議論の埌、この問題に察凊する方法の蚈画の基本がありたす。 ただし、パフォヌマンスぞの圱響を実際に調査し、最終的な詳现を把握するには、ある皋床の支揎が必芁です。


元の問題は次のずおりです。

倀がty2に収たらない堎合、結果は未定矩です。

1.04E+17 as u8
A-LLVM C-bug I-unsound 💥 P-medium T-lang

最も参考になるコメント

LLVMでfloatをintキャストに飜和させるための組み蟌み関数を実装するための䜜業を開始したした https 

それがどこかに行けば、飜和セマンティクスを取埗するための比范的オヌバヌヘッドの少ない方法を提䟛したす。

党おのコメント234件

指名

P-highで受け入れられ、10183ず同じ理由

これは蚀語レベルで埌方互換性がないず思いたす。 正垞に機胜しおいたコヌドが機胜を停止するこずはありたせん。 指名。

P-highに倉曎、10183ず同じ理由

これず10185をどのように解決するこずを提案したすか 動䜜が定矩されおいるかどうかは、キャストされる数倀の動的な倀に䟝存するため、唯䞀の解決策は動的チェックを挿入するこずであるように思われたす。 算術オヌバヌフロヌではこれを実行したくないこずに同意しおいるようですが、キャストオヌバヌフロヌでは実行できたすか

「安党な倉換」を実行する組み蟌み関数をLLVMに远加できたす。 @zwarichは他のアむデアを持っおいるかもしれたせん。

珟時点での唯䞀の解決策は、タヌゲット固有の組み蟌み関数を䜿甚するこずです。 少なくずも私が尋ねた誰かによるず、それはJavaScriptCoreが行うこずです。

ああ、それなら簡単です。

ping @pnkfelixこれは新しいオヌバヌフロヌチェックのものでカバヌされおいたすか

これらのキャストは、デバッグアサヌションを䜿甚したrustcによっおチェックされたせん。

私はこれを喜んで凊理したすが、具䜓的な解決策が必芁です。 個人的には、非垞によく䌌た問題なので、オヌバヌフロヌした敎数挔算ず䞀緒にチェックする必芁があるず思いたす。 私は私たちが䜕をするかは本圓に気にしたせん。

この問題は、特定の定数匏で䜿甚された堎合、珟圚ICEを匕き起こしおいるこずに泚意しおください。

これにより、安党な錆でメモリの安党性を䟵害するこずができたす。このフォヌラムの投皿の䟋

Undefs、ハァッ Undefは楜しいです。 それらは䌝播する傟向がありたす。 数分のラングリングの埌..

#[inline(never)]
pub fn f(ary: &[u8; 5]) -> &[u8] {
    let idx = 1e100f64 as usize;
    &ary[idx..]
}

fn main() {
    println!("{}", f(&[1; 5])[0xdeadbeef]);
}

-Oを䜿甚したシステムのセグメンテヌション違反毎晩遅く。

安党な錆でのメモリ安党性の違反を考慮しお、I-unsoundでマヌクしたす。

@bluss 、これは私にずっおsegfualtではなく、アサヌション゚ラヌを䞎えるだけです。 私がそれを远加したのでタグを倖したす

ため息、-Oを忘れお、タグを付け盎したした。

P-highに再指名。 どうやらこれはある時点でP-highでしたが、時間の経過ずずもに䜎くなりたした。 これは正確さのためにかなり重芁なようです。

線集トリアヌゞコメントに反応せず、手動でラベルを远加したした。

オヌバヌフロヌの前䟋シフトなどは、䜕らかの動䜜に萜ち着くこずであるように思われたす。 Javaは範囲を法ずしお結果を生成するようですが、これは䞍合理ではないようです。 それを凊理するために必芁なLLVMコヌドの皮類がわかりたせん。

https://docs.oracle.com/javase/specs/jls/se7/html/jls-5.html#jls -5.1.3によるず、JavaはNaN倀が0ず無限倧にマップされるこずも保蚌したす最小/最倧の衚珟可胜な敎数に。 さらに、倉換のJavaルヌルは、単なるラッピングよりも耇雑であり、飜和 intたたはlongぞの倉換の堎合ずラッピングより小さな敎数型ぞの倉換の堎合の組み合わせにするこずができたす。 、 必芁に応じお。 Javaから倉換アルゎリズム党䜓を耇補するこずは確かに可胜ですが、キャストごずにかなりの量の操䜜が必芁になりたす。 特に、LLVMでのfpto[us]i操䜜の結果が未定矩の動䜜を瀺さないようにするには、範囲チェックが必芁になりたす。

別の方法ずしお、float-> intキャストは、元の倀の切り捚おが宛先タむプの倀たたは[iu]size ずしお衚される堎合にのみ有効であるこずが保蚌されるこずをお勧めしたす。倀が忠実に衚珟されおいない堎合にパニックを匕き起こすデバッグビルドに関するアサヌションがありたす。

Javaアプロヌチの䞻な利点は、倉換関数が完党であるこずですが、これは予期しない動䜜が忍び寄る可胜性があるこずも意味したす。未定矩の動䜜は防止されたすが、キャストが実際に意味があるかどうかをチェックしないようにだたされやすくなりたす。 これは残念ながら他のキャストにも圓おはたりたす心配:)。

もう1぀のアプロヌチは、珟圚算術挔算に䜿甚されおいるアプロヌチず䞀臎したす。リリヌスでのシンプルで効率的な実装、デバッグでの範囲チェックによっおトリガヌされるパニックです。 残念ながら、他のasキャストずは異なり、これによりそのような倉換がチェックされたす。これはナヌザヌにずっお驚くべきこずですただし、算術挔算ずの類䌌性がここで圹立぀堎合がありたす。 これも䞀郚のコヌドを壊したすが、AFAICTは、珟圚未定矩の動䜜に䟝存しおいるコヌドでのみ発生するはずです぀たり、未定矩の動䜜を「任意の敎数を返したしょう。明らかにどちらでもかたいたせん」をパニックに眮き換えたす。

問題は「敎数を返そう、どちらでもかたわない」ではなく、ランダムな倀ではなく錻の悪魔の倀であるundefを匕き起こし、LLVMはundefが発生しないず想定できるこずです。ひどい間違ったこずをする最適化を可胜にしたす。 それがランダムな倀であるが、決定的にundefではない堎合、それは健党性の問題を修正するのに十分です。 衚珟できない倀がどのように衚珟されるかを定矩する必芁はありたせん。undefを防ぐ必芁がありたす。

@ rust-lang / compilerミヌティングで議論されたした。 最も䞀貫した行動方針は残っおいたす

  1. オヌバヌフロヌチェックが有効になっおいる堎合は、䞍正なキャストやパニックをチェックしたす。
  2. それ以倖の堎合は、フォヌルバック動䜜が必芁です。有効な倀の実行時コストが最小理想的にはれロである必芁がありたすが、LLVM undefでない限り、正確な動䜜はそれほど重芁ではありたせん。

䞻な問題は、オプション2の具䜓的な提案が必芁なこずです。

トリアヌゞP-medium

@nikomatsakis as珟圚、デバッグビルドでパニックになったこずはありたすか そうでない堎合は、䞀貫性ず予枬可胜性のために、そのたたにしおおくこずが望たしいようです。 算術ず同じように、あるべきだず思いたすが、それは別の過去の議論です。

それ以倖の堎合は、フォヌルバック動䜜が必芁です。有効な倀の実行時コストが最小理想的にはれロである必芁がありたすが、LLVM undefでない限り、正確な動䜜はそれほど重芁ではありたせん。

具䜓的な提案数字ず指数をu64ずしお抜出し、数字を指数でビットシフトしたす。

fn f64_as_u64(f: f64) -> u64 {
    let (mantissa, exponent, _sign) = f.integer_decode();
    mantissa >> ((-exponent) & 63)
}

はい、それはれロコストではありたせんが、ある皋床最適化可胜であり integer_decode inlineずマヌクした方がよいでしょう、少なくずも決定論的です。 float-> intキャストを拡匵する将来のMIRパスは、floatがキャストしおも問題ないこずが保蚌されおいるかどうかを分析し、この重い倉換をスキップする可胜性がありたす。

LLVMには倉換関数甚のプラットフォヌム組み蟌み関数がありたせんか

線集 @zwarichは蚀ったずっず前に

珟時点での唯䞀の解決策は、タヌゲット固有の組み蟌み関数を䜿甚するこずです。 少なくずも私が尋ねた誰かによるず、それはJavaScriptCoreが行うこずです。

なぜパニックにさえ悩むのですか AFAIK、 @ glaebhoerlは正しい、 asは切り捚お/拡匵するこずになっおいる、オペランドをチェックしない。

2016幎3月5日土曜日03:47:55 AM -0800に、GáborLehelは次のように曞いおいたす。

@nikomatsakis as珟圚、デバッグビルドでパニックになったこずはありたすか そうでない堎合は、䞀貫性ず予枬可胜性のために、そのたたにしおおくこずが望たしいようです。 算術ず同じように、あるべきだず思いたすが、それは別の過去の議論です。

本圓。 私はそれが説埗力があるず思いたす。

2016幎3月9日氎曜日02:31:05 AM -0800、Eduard-MihaiBurtescuは次のように曞いおいたす。

LLVMには倉換関数甚のプラットフォヌム組み蟌み関数がありたせんか

線集

珟時点での唯䞀の解決策は、タヌゲット固有の組み蟌み関数を䜿甚するこずです。 少なくずも私が尋ねた誰かによるず、それはJavaScriptCoreが行うこずです。

なぜパニックにさえ悩むのですか AFAIK、 @ glaebhoerlは正しい、 asは切り捚お/拡匵するこずになっおいる、オペランドをチェックしない。

はい、私は以前に間違っおいたず思いたす。 asは「チェックされおいない切り捚お」です
オペレヌタヌ、良くも悪くも、䞀貫性を保぀のが最善のようです
その哲孊で。 タヌゲット固有の組み蟌み関数を䜿甚するこずは完党に可胜性がありたす
でも良い解決策

@nikomatsakis 動䜜はただ定矩されおいないようですか それに関する蚈画に぀いおの最新情報を教えおいただけたすか

はるかに少ない数でこれに遭遇しただけです

    let x: f64 = -1.0;
    x as u8

最適化に応じお0、16などの結果になりたすが、255ずしお定矩されるこずを期埅しおいたので、 x as i16 as u8を蚘述する必芁はありたせん。

@gmorenz !0u8を詊したしたか

意味をなさないコンテキストでは、[-255、255]の範囲で、ネットワヌクを介しお送信されたデヌタの倉換からf64を取埗しおいたした。 私はそれがうたくラップするこずを望んでいたした <i32> as u8がラップするのずたったく同じ方法で。

これが「killundef」 http://lists.llvm.org/pipermail/llvm-dev/2016-October/106182.htmlに察する最近のLLVMの提案ですが、これが自動的に解決されるかどうかを知るのに十分な知識はほずんどありたせん。この問題。

圌らはundefをpoisonに眮き換えおおり、セマンティクスはわずかに異なりたす。 int-> floatが定矩された動䜜をキャストするこずはありたせん。

飜和キャストを行うための明瀺的な方法を提䟛する必芁がありたす

https://github.com/rust-lang/rust/issues/10184#issuecomment -139858153を考えるず、このようにI-crashずマヌクする必芁があるようです。

今日#rust-beginnersこれに぀いお質問がありたしたが、誰かが野生でそれに遭遇したした。

私が@jimblandyで曞いおいる本、_Programming Rust_は、このバグに぀いお蚀及しおいたす。

数皮類のキャストが蚱可されおいたす。

  • 数倀は、組み蟌みの数倀タむプから他のタむプにキャストできたす。

    ...

    ただし、この蚘事の執筆時点では、倧きな浮動小数点倀を小さすぎお衚珟できない敎数型にキャストするず、未定矩の動䜜が発生する可胜性がありたす。 これにより、安党なRustでもクラッシュが発生する可胜性がありたす。 これは、コンパむラgithub.com/rust-lang/rust/issues/10184のバグ

この章の締め切りは5月19日です。最埌の段萜を削陀したいのですが、少なくずも最初に䜕らかの蚈画を立おる必芁があるず思いたす。

どうやら珟圚のJavaScriptCoreはx86で䜿甚しおいたす。 圌らはCVTTSD2SI呜什を䜿甚し、倀が範囲倖の堎合はいく぀かのヘアリヌC ++にフォヌルバックしたす。 珟圚、範囲倖の倀が爆発しおいるため、その呜什を䜿甚するずフォヌルバックなしで、1぀のアヌキテクチャのみではありたすが、珟圚の状態が改善されたす。

正盎なずころ、 as数倀キャストを廃止し、代わりにFromずTryFromたたはconvcrateのようなものを䜿甚する必芁があるず思いたす。

たぶんそうかもしれたせんが、それは私には盎亀しおいるようです。

OK、この䌚話党䜓を読み盎したした。 この操䜜はパニックにならないずいう合意があるず思いたす asずの䞀般的な䞀貫性のため。 行動がどうあるべきかに぀いおは、2぀の䞻芁な候補がありたす。

  • ある皮の定矩された結果

    • プロこれは、これたでの私たちの䞀般的な哲孊ず最倧限に䞀臎しおいるず思いたす。

    • 短所この堎合、特定の定矩された結果を生成するための真にポヌタブルな方法はないようです。 これは、範囲倖の倀に察しお䜕らかのフォヌルバックを䌎うプラットフォヌム固有の組み蟌み関数を䜿甚するこずを意味したすたずえば、飜和状態ぞのフォヌルバック、@ oli-obkが提案したこの関数、 Javaの定矩、たたは「ヘアリヌC ++」ぞのフォヌルバック

    • 最悪の堎合、「範囲倖」の堎合にいく぀かのifを挿入するこずができたす。

  • 未定矩の倀未定矩の動䜜ではありたせん

    • 長所これにより、各プラットフォヌムで䜿甚可胜なプラットフォヌム固有の組み蟌み関数を䜿甚できたす。

    • 短所それは携垯性の危険です。 䞀般に、少なくずも蚀語では、未定矩の結果をあたり頻繁に䜿甚しおいないように感じ

最初のケヌスで結果がどうあるべきかに぀いお明確な前䟋があるかどうかは私にはわかりたせんか

それを曞き留めた埌、私の奜みは決定論的な結果を維持するこずです。 決定論の線を匕くこずができるすべおの堎所が勝利であるように私は感じたす。 しかし、結果がどうあるべき

飜和は理解できお䟿利なように芋えるので奜きですが、 u64 as u32が切り捚おを行う方法ずはどういうわけか䞀臎しおいないようです。 したがっお、おそらく切り捚おに基づくある皮の結果は理にかなっおいたす。これはおそらく@ oli-obkが提案したものだず思いたす。そのコヌドが䜕を意図しおいるのか完党には理解しおいたせん。 =

私のコヌドは、0..2 ^ 64の範囲の倀に正しい倀を䞎え、それ以倖のすべおには決定論的ですが停の倀を䞎えたす。

浮動小数点数は仮数^指数で衚されたす。たずえば、 1.0は(2 << 52) ^ -52あり、ビットシフトず指数はバむナリで同じものであるため、シフトを逆にするこずができたすしたがっお、指数ず右の吊定シフト。

決定論の堎合は+1。

人間にずっお意味のある2぀のセマンティクスがありたす。コンパむラヌが蚈算を最適化できない堎合は、範囲内の倀に察しおどちらか速い方を遞択する必芁があるず思いたす。 倀が範囲内にあるこずをコンパむラヌが認識しおいる堎合、䞡方のオプションで同じ結果が埗られるため、同等に最適化できたす。

  • 圩床範囲倖の倀はIntType::max_value() / min_value() 
  • モゞュロ範囲倖の倀は、最初にbigintに倉換しおから、切り捚おるこずによっお凊理されたす

次の衚は、䞡方のオプションを完党に指定するこずを目的ずしおいたす。 Tは、任意のマシン敎数型です。 TminずTmaxはT::min_value()ずT::max_value()です。 RTZvは、vの数孊倀を取り、れロに向かっお䞞めお数孊敎数を取埗するこずを意味したす。

v | v as T 圩床| v as T モゞュロ
---- | ---- | --------
範囲内Tmin <= v <= Tmax| RTZv| RTZv
負のれロ| 0 | 0
NaN | 0 | 0
むンフィニティ| Tmax | 0
-むンフィニティ| Tmin | 0
v> Tmax | Tmax | Tに合うように切り捚おられたRTZv
v <Tmin | Tmin | Tに合うように切り捚おられたRTZv

ECMAScript暙準では、操䜜ToInt32 、ToUint32、ToInt16、ToUint16、ToInt8、ToUint8が指定されおいたす。䞊蚘の「モゞュロ」オプションの目的は、すべおの堎合にこれらの操䜜を䞀臎させるこずです。

ECMAScriptは、䞊蚘のどちらの堎合にも䞀臎しToInt8Clampも指定したす

@ oli-obkの提案は、範囲内の倀に぀いお、蚈算が高速かどうかを怜蚎する䟡倀のある3番目の方法です。

@ oli-obk笊号付き敎数型はどうですか

別の提案をミックスに投入するu128がフロヌトにキャストするこずを安党ではないずマヌクし、人々にそれを凊理する方法を明瀺的に遞択するように匷制したす。 u128は珟圚かなりたれです。

@Manishearth私は同様のセマンティクス敎数→浮動小数点数ずしお浮動小数点数→敎数を望んでいたす。 どちらもUBに察応しおおり、float→integerを安党でなくするこずはできないため、integer→floatも安党でなくなるこずは避けおください。

float→integersaturatingの堎合、AFAICTが高速になりたす andシヌケンス、テスト+ゞャンプフロヌトの比范ずゞャンプ、すべお最新のアヌチで0.66たたは0.5 2-3サむクルになりたす。 個人的には、範囲内の倀が可胜な限り高速である限り、決定する正確な動䜜を気にするこずはできたせんでした。

オヌバヌフロヌのように動䜜させるのは理にかなっおいたすか したがっお、デバッグビルドでは、未定矩の動䜜でキャストを行うずパニックになりたす。 次に、 1.04E+17.saturating_cast::<u8>() 、 unsafe { 1.04E+17.unsafe_cast::<u8>() }などのキャスト動䜜を指定するためのメ゜ッドを䜜成できたす。

ああ、問題はu128だけにあるず思ったので、どちらの方法でも安党ではありたせん。

@cryze UBは、安党なコヌドのリリヌスモヌドでも存圚しおはなりたせん。 オヌバヌフロヌはただ定矩された動䜜です。

ずはいえ、デバッグでパニックになり、リリヌス時に玠晎らしいでしょう。

これは以䞋に圱響したす

  • f32 -> u8, u16, u32, u64, u128, usize  -1f32 as _すべおのために、 f32::MAX as _すべおが、u128甚
  • f32 -> i8, i16, i32, i64, i128, isize すべおf32::MAX as _ 
  • f64 ->すべおのintすべおf64::MAX as _ 

f32::INFINITY as u128もUBです

@CryZe

オヌバヌフロヌのように動䜜させるのは理にかなっおいたすか したがっお、デバッグビルドでは、未定矩の動䜜でキャストを行うずパニックになりたす。

これは私が最初に考えたものですが、 as倉換は珟圚パニックになるこずはないこずを思い出したした良くも悪くも、 asでオヌバヌフロヌチェックを行いたせん。 したがっお、最も類䌌したこずは、「定矩された䜕かを行う」こずです。

FWIW、「kill undef」は、実際には、メモリの安党性を修正する方法を提䟛したすが、結果は非決定的です。 重芁なコンポヌネントの1぀は次のずおりです。

3の䌝播を停止する新しい呜什 'y = freezex'を䜜成したす
毒。 入力がpoisonの堎合、任意ですが固定された、
倀。 叀いundefず同様ですが、䜿甚するたびに
入力倀を返すだけです。

undefが今日のメモリ安党性に違反するために䜿甚される理由は、undefが䜿甚間、特に境界チェックずそれに続くポむンタ挔算の間で倀を魔法のように倉曎できるためです。 危険なキャストが行われるたびにrustcがフリヌズを远加した堎合、未知の倀が埗られたすが、それ以倖の堎合は正垞に動䜜したす。 もちろん、キャストに察応するマシン呜什は倉動する倀ではなく単䞀の倀を生成するため、パフォヌマンス面では、フリヌズは基本的にここでは無料です。 オプティマむザが䜕らかの理由でキャスト呜什を耇補したいず感じた堎合でも、範囲倖の入力の結果は通垞、特定のアヌキテクチャで決定論的であるため、耇補しおも安党です。

...しかし、誰かが疑問に思っおいたずしおも、アヌキテクチャ間で決定論的ではありたせん。 x86は、すべおの䞍正な入力に察しお0x80000000を返したす。 ARMは範囲倖の入力に察しお飜和し、この擬䌌コヌドを正しく読んでいる堎合NaNに察しお0を返したす。 したがっお、目暙が決定論的でプラットフォヌムに䟝存しない結果を生成するこずである堎合、プラットフォヌムのfp-to-int組み蟌み関数を䜿甚するだけでは十分ではありたせん。 少なくずもARMでは、ステヌタスレゞスタで䟋倖をチェックする必芁もありたす。 これはそれ自䜓にいくらかのオヌバヌヘッドがあるかもしれたせん、そしお確かに組み蟌みを䜿甚するこずがただしなかったずいう䞇が䞀のむベントでの自動ベクトル化を防ぎたす。 たたは、通垞の比范操䜜を䜿甚しお範囲内の倀を明瀺的にテストしおから、通垞のfloat-to-intを䜿甚するこずもできたす。 オプティマむザヌの方がずっずいいですね 

asコンバヌゞョンは珟圚パニックになるこずはありたせん

ある時点で、 +をパニックに倉曎したしたデバッグモヌド。 以前はUBだったケヌスで、 asパニックが発生しおも、ショックを受けるこずはありたせん。

チェックに関心がある堎合これを行う必芁がありたす、 as非掚奚にするかこれが唯䞀の良いオプションであるナヌスケヌスはありたすか、少なくずもそれを䜿甚しないようにアドバむスし、人々を次のようなものに移す必芁がありたす。代わりにTryFromずTryInto䜿甚したす。これは、 asをそのたたにしおおくこずが決定されたずきに、元に戻す予定であるず述べたものです。 議論されおいるケヌスは、抜象的には、チェックを行わないようにasがすでに定矩されおいるケヌスず質的に異なるずは思いたせん。 違いは、実際には、これらのケヌスの実装は珟圚䞍完党であり、UBがあるこずです。 あなたがに頌るこずができない䞖界asチェックを行うほずんどの皮類のために、それはないので、そしおあなたはパニックではない、それに頌るこずはできたせん理由はいく぀かのタむプのため、それはある、およびそれは䞀貫性がなく、私たちはただ非掚奚ではありたせん。私にずっおはそれらすべおの䞭で最悪のようです。

したがっお、この時点で、 @ jorendorffは基本的に、私にずっお最良の蚈画であるず思われるものを列挙し

  • asには、決定論的な動䜜がありたす。
  • それがどれほど賢明であるか、そしおそれがどれほど効率的であるかの組み合わせに基づいお行動を遞びたす

圌は3぀の可胜性を列挙したした。 残りの䜜業は、それらの可胜性を調査するこず、たたは少なくずもそのうちの1぀を調査するこずだず思いたす。 ぀たり、実際に実装しお、それがどれほど「遅い」か「速い」かを感じ取っおみおください。

それを刺したいずいうモチベヌションを感じおいる人はいたすか 誰かを匕き付けるこずを期埅しお、これにE-help-wantedタグを付けたす。 @ oli-obk

ええず、私はクロスプラットフォヌムの䞀貫性に代償を払うのではなく/ガベヌゞむンです。どのガベヌゞが出るかは気にしたせんただし、デバッグアサヌションは非垞に圹立ちたす。

珟圚、Rustのすべおの䞞め/切り捚お関数は非垞に遅いため现心の泚意をasお正確に実装された関数呌び出し、

as裞のcvttss2si以倖のものにする堎合は、それだけの安定した代替手段も远加しおください。

@pornelこれは理論的な皮類のUBだけではなく、ubであるこずを無芖すれば問題はありたせんが、珟実の䞖界に圱響を及がしたす。 実䞖界のコヌド䟋から41799を抜出したした。

@ est31 UBのたたにしおおくのは間違っおいるこずに同意したすが、UBの解決策ずしおfreeze提案されおいるのを芋おきたした。 それを定矩された決定論的倀にするAFAIK、あなたはただどちらを蚀うこずができたせん。 その振る舞いは私には問題ありたせん。

たずえば堎合、私は倧䞈倫ず思いたすので、 u128::MAX as f32決定論的に生成17.5 x86版、および999.0 x86-64の䞊、および-555 ARM䞊。

freezeは、定矩された、決定論的な、指定されおいない倀を生成したせん。 その結果は䟝然ずしお「コンパむラヌが奜む任意のビットパタヌン」であり、同じ操䜜の䜿甚党䜓でのみ䞀貫しおいたす。 これは、人々が䞊蚘で収集したUB生成の䟋を回避する可胜性がありたすが、これは埗られたせん。

f32ずしおのu128 :: MAXは、x86で17.5、x86-64で999.0、ARMで-555を決定論的に生成したした。

たずえば、LLVMがu128::MAX as f32がオヌバヌフロヌし、それをfreeze poisonに眮き換えるこずに気付いた堎合、x86_64でのfn foo() -> f32 { u128::MAX as f32 }有効な匕き䞋げは次のようになりたす。

foo:
  ret

぀たり、リタヌンレゞスタに最埌に保存されたものを返すだけです

そうですか。 それは私の䜿甚にはただ受け入れられたす範囲倖の倀を期埅する堎合は、事前にクランプを行いたす。範囲内の倀を期埅するがそうではない堎合は、䜕があっおも正しい結果が埗られたせん 。

倀がフリヌズされおいる限り、範囲倖のフロヌトキャストが任意の倀を返すこずに問題はないので、それ以䞊の未定矩の動䜜を匕き起こすこずはありたせん。

freezeようなものがLLVMで利甚できたすか それは玔粋に理論的な構成だず思いたした。

@nikomatsakis  poisonずは異なりそのように䜿甚されるのを芋たこずがありたせん-これはpoison / undefの蚈画された改良です。

freezeは、今日のLLVMにはたったく存圚したせん。 提案されただけですこのPLDIペヌパヌは自己完結型ですが、メヌリングリストでも倚く議論されおいたす。 この提案にはかなりの賛同が埗られおいるようですが、もちろんそれが採甚される保蚌はなく、タむムリヌに採甚されるこずははるかに少ないです。 ポむンタヌ型からのポむンタヌ型の削陀は䜕幎もの間受け入れられおきたしたが、ただ行われおいたせん。

ここで提案されおいる倉曎に぀いおより広範な議論を埗るためにRFCを開きたいですか IMO、 asのパフォヌマンスに圱響を䞎える可胜性のあるものはすべお論争になりたすが、人々に圌らの声を聞かせる機䌚を䞎えなければ、二重に論争になりたす。

私はJulia開発者ですが、同じLLVMバック゚ンドを共有しおいるため、同様の問題が発生しおいるため、この問題をしばらく远跡しおいたす。 興味がある堎合は、これが私たちが決めたものです私のマシンの単䞀の機胜のおおよそのタむミングで

  • unsafe_trunc(Int64, x)は、察応するLLVM組み蟌みfptosi 1.5 nsに盎接マップされたす
  • trunc(Int64, x)は、範囲倖の倀3 nsに察しお䟋倖をスロヌしたす
  • convert(Int64, x)は、範囲倖たたは敎数以倖の倀6 nsに察しお䟋倖をスロヌしたす

たた、メヌリングリストで未定矩の振る舞いをもう少し明確にするこずに぀いお

@bstrie RFCは問題ありたせんが、デヌタがあるず間違いなく圹立぀ず思いたす。 ただし、@ simonbyrneのコメントはその点で非垞に圹立ちたす。

JSセマンティクス前述のモゞュロ@jorendorff ず「飜和」列のように芋えるJavaセマンティクスをいじっおみたした。 これらのリンクが期限切れになった堎合、それはJSずJavaです。

たた、Rustでの飜和の簡単な実装を䜜成したした。これは正しいず思いたす たた、いく぀かのベンチマヌク数倀も取埗したした。 興味深いこずに、飜和実装は組み蟌みの実装より2〜3倍遅いこずが@ simonbyrneが2倍遅いだけで芋぀けたものずは異なりたす。

Rustで「mod」セマンティクスを実装する方法が完党にはわかりたせん...

しかし、私には、パフォヌマンスが必芁な人のために、倚数のf32::as_u32_unchecked()メ゜ッドなどが必芁になるこずは明らかです。

パフォヌマンスが必芁な人には、たくさんのf32::as_u32_unchecked()メ゜ッドなどが必芁になるこずは明らかです。

それは残念です-それずも、安党であるが実装定矩のバリアントを意味したすか

実装で定矩された高速デフォルトのオプションはありたせんか

@eddyb私たちはただ持っおいるだろうず考えおいたunsafe fn as_u32_unchecked(self) -> u32にf32䜕に盎接アナログであるず、このようなas今日です。

私が曞いたRustの実装が最適であるずは断蚀できたせんが、このスレッドを読むずきは、ほずんどの堎合、速床よりも決定論ず安党性の方が重芁であるずいう印象を受けたした。 unsafe゚スケヌプハッチはフェンスの向こう偎にいる人のためのものです。

では、プラットフォヌムに䟝存する安䟡なバリアントはありたせんか 私は速い䜕かが、䞍特定の倀を䞎えるずき、境界の倖で安党ですしたいです。 䞀郚の入力にUBを䜿甚したくないので、もっずうたくできれば、䞀般的な䜿甚には危険すぎるず思いたす。

私の知る限り、すべおではないにしおもほずんどのプラットフォヌムで、この倉換を実装するための暙準的な方法は、UBではない範囲倖の入力に察しお䜕かを行いたす。 しかし、LLVMには、UBよりもそのオプションそれが䜕であれを遞択する方法がないようです。 LLVM開発者に、範囲倖の入力で「指定されおいないがundef / poison 」結果を生成する組み蟌み関数を導入するように説埗できれば、それを䜿甚できたす。

しかし、このスレッドの誰かが説埗力のあるRFCllvm-devリストにあるを䜜成し、賛同を埗お、それを実装する必芁があるず私は掚枬したす私たちが気にするバック゚ンドで、そしお他のフォヌルバック実装でタヌゲット。 llvm-devに既存のキャストを非UBにするよう説埗するよりもおそらく簡単ですが「これによりCおよびC ++プログラムが遅くなるか」などの質問を回避できるため、それでもそれほど簡単ではありたせん。

これらから遞択する堎合に備えお

圩床範囲倖の倀はIntType :: max_value/ min_valueになりたす
モゞュロ範囲倖の倀は、最初にbigintに倉換しおから、切り捚おるこずによっお凊理されたす

浮動小数点の絶察粟床は倀が倧きくなるずすぐに䜎䞋するため、IMOのみの飜和はここでは意味がありたす。したがっお、ある時点で、モゞュロはすべおのれロのように圹に立たないものになりたす。

私はこれをマヌクE-needs-mentorずし、それをタグ付けWG-compiler-middle IMPL期間は、これをさらにを調査する絶奜の機䌚であるかもしれないず思われるので、 蚘録の蚈画に関する私の既存の

@nikomatsakis

IIRC LLVMは、最終的にfreeze実装するこずを蚈画しおいたす。これにより、 freeze実行するこずでUBを凊理できるようになりたす。

これたでの私の結果 https 

_arrayバリアントは、1024個の倀のルヌプを実行したす。
_cast x as i32
_clipx.minMAX.maxMINas i32
_panicxが範囲倖の堎合はパニックになりたす
_zero範囲倖の堎合、結果をれロに蚭定したす

test bench_array_cast       ... bench:       1,840 ns/iter (+/- 37)
test bench_array_cast_clip  ... bench:       2,657 ns/iter (+/- 13)
test bench_array_cast_panic ... bench:       2,397 ns/iter (+/- 20)
test bench_array_cast_zero  ... bench:       2,671 ns/iter (+/- 19)
test bench_cast             ... bench:           2 ns/iter (+/- 0)
test bench_cast_clip        ... bench:           2 ns/iter (+/- 0)
test bench_cast_panic       ... bench:           2 ns/iter (+/- 0)
test bench_cast_zero        ... bench:           2 ns/iter (+/- 0)

おそらく、個々の操䜜の結果を敎数に䞞める必芁はありたせん。 明らかに、これらの2 ns / iterの背埌にはいく぀かの違いがあるはずです。 それずも、4぀のバリアントすべおで_正確に_ 2 nsのようになっおいたすか

@ sp-1234郚分的に最適化されおいるのだろうか。

@ sp-1234枬定するには速すぎたす。 非アレむベンチマヌクは基本的に圹に立たない。
単䞀倀関数を#[inline(never)]経由の関数に匷制するず、2ns察3nsになりたす。

@ arielb1
freezeに関しおいく぀か予玄がありたす。 私が正しく理解しおいれば、凍結されたundefは任意の倀を含めるこずができ、䜿甚しおも倉化したせん。 実際には、コンパむラはおそらくレゞスタたたはスタックスロットを再利甚したす。

ただし、これは、初期化されおいないメモリを安党なコヌドから読み取るこずができるこずを意味したす。 これにより、Heartbleedのように、秘密のデヌタが挏掩する可胜性がありたす。 これがRustの芳点から本圓にUBず芋なされるかどうかは議論の䜙地がありたすが、明らかに望たしくないようです。

@ s3bkのベンチマヌクをロヌカルで実行したした。 スカラヌバヌゞョンが完党に最適化されおいるこずを確認できたす。たた、配列バリアントのasmも疑わしいほど適切に最適化されおいるように芋えたす。たずえば、ルヌプはベクトル化されおいたす。

残念ながら、 black_boxスパムするこずは圹に立たないようです。 asmが有甚な䜜業を行っおいるこずはわかりたすが、ベンチマヌクを実行するず、スカラヌベンチマヌクに察しお䞀貫しお0nsが埗られたす1nsを瀺すcast_zeroを陀く。 @alexcrichtonがベンチマヌクで100回比范を実行したこずが゜ヌスコヌド

test bench_cast             ... bench:          53 ns/iter (+/- 0)
test bench_cast_clip        ... bench:         164 ns/iter (+/- 1)
test bench_cast_panic       ... bench:         172 ns/iter (+/- 2)
test bench_cast_zero        ... bench:         100 ns/iter (+/- 0)

アレむのベンチマヌクは、私がそれらを信頌するにはあたりにも倚様です。 たあ、正盎なずころ、私はずにかくtestベンチマヌクむンフラストラクチャに懐疑的です。特に、以前に取埗したフラットな0nsず比范しお䞊蚘の数倀を確認した埌はそうです。 さらに、ベヌスラむンずしおの black_box(x); 100回の反埩でも34nsかかるため、これらの数倀を確実に解釈するこずはさらに困難になりたす。

泚目に倀する2぀のポむント

  • NaNを具䜓的に凊理しおいたせんが0ではなく-infを返したすか、 cast_clip実装は@alexcrichtonの飜和キャストよりも遅いようです実行ず私の実行のタむミングはasほが同じであるこずに泚意しおください
  • @ s3bkの配列の結果ずは異なり、 cast_panicは他のチェックされたキャストよりも遅いこずがわかりたす。 たた、アレむベンチマヌクの速床がさらに䜎䞋しおいるこずもわかりたす。 たぶん、これらのものは、マむクロアヌキテクチャの詳现やオプティマむザのムヌドに倧きく䟝存しおいたすか

蚘録のために、私はrustc 1.21.0-nightlyd692a91fa 2017-08-04、 -C opt-level=3 、軜負荷のi7-6700Kで枬定したした。


結論ずしお、これたでのずころ信頌できるデヌタはなく、より信頌できるデヌタを取埗するのは難しいように思われるず結論付けおいたす。 さらに、実際のアプリケヌションが実時間の1でもこの操䜜に費やしおいるこずを匷く疑っおいたす。 したがっお、 -Zフラグの背埌で、 rustcに

線集可胜であれば、さたざたなアヌキテクチャARMなどやマむクロアヌキテクチャでこのようなベンチマヌクを実行するこずもお勧めしたす。

私はさびにあたり詳しくないこずを認めたすが、この行は埮劙に間違っおいるず思いたす std::i32::MAX 2 ^ 31-1はFloat32ずしお正確に衚珟できないため、 std::i32::MAX as f32は最も近い衚珟可胜な倀2 ^ 31に䞞められたす。 この倀が匕数xずしお䜿甚される堎合、結果は技術的に未定矩です。 厳密な䞍等匏に眮き換えるず、このケヌスが修正されたす。

ええ、私たちは以前サヌボでたさにその問題を抱えおいたした。 最終的な解決策は、f64にキャストしおからクランプするこずでした。

他の解決策もありたすが、それらはかなりトリッキヌであり、錆はこれをうたく凊理するための優れたAPIを公開しおいたせん。

䞊限ずしお0x7FFF_FF80i32を䜿甚し、-0x8000_0000i32を䜿甚するず、f64にキャストせずにこれを解決できたす。
線集正しい倀を䜿甚しおください。

0x7fff_ff80を意味しおいるず思いたすが、厳密な䞍等匏を䜿甚するだけで、コヌドの意図が明確になる可胜性がありたす。

x < 0x8000_0000u32 as f32  それはおそらく良い考えでしょう。

提案されおいるすべおの決定論的オプションに぀いお考えるず、ずにかく頻繁に行われるず思うので、クランプは䞀般的に最も有甚なものです。 倉換タむプが実際に飜和状態であるず文曞化される堎合、手動クランプは䞍芁になりたす。

提案された実装はマシン呜什に適切に倉換されず、分岐に倧きく䟝存しおいるため、私は少しだけ心配しおいたす。 分岐するず、パフォヌマンスは特定のデヌタパタヌンに䟝存したす。 䞊蚘のテストケヌスでは、同じ分岐が垞に行われ、プロセッサには以前の倚くのルヌプ反埩からの良奜な分岐予枬デヌタがあるため、すべおが比范的高速に芋えたす。 珟実の䞖界はおそらくそのようには芋えないでしょう。 さらに、分岐は、コヌドをベクトル化するコンパむラヌの機胜を損ないたす。 私は@rkruppeの意芋に同意したせん。この操䜜は、ベクトル化ず組み合わせおテストするべきではないずいうものです。 高性胜コヌドではベクトル化が重芁であり、䞀般的なアヌキテクチャで単玔なキャストをベクトル化できるこずは重芁な芁件です。

䞊蚘の理由により、飜和セマンティクスず@simonbyrneの修正を䜿甚した詊しおみたした。 u16 、 i16 、 i32はすべおわずかに異なるケヌスをカバヌする必芁があるため、パフォヌマンスが異なるため、実装したした。

結果

test i16_bench_array_cast       ... bench:          99 ns/iter (+/- 2)
test i16_bench_array_cast_clip  ... bench:         197 ns/iter (+/- 3)
test i16_bench_array_cast_clip2 ... bench:         113 ns/iter (+/- 3)
test i16_bench_cast             ... bench:          76 ns/iter (+/- 1)
test i16_bench_cast_clip        ... bench:         218 ns/iter (+/- 25)
test i16_bench_cast_clip2       ... bench:         148 ns/iter (+/- 4)
test i16_bench_rng_cast         ... bench:       1,181 ns/iter (+/- 17)
test i16_bench_rng_cast_clip    ... bench:       1,952 ns/iter (+/- 27)
test i16_bench_rng_cast_clip2   ... bench:       1,287 ns/iter (+/- 19)

test i32_bench_array_cast       ... bench:         114 ns/iter (+/- 1)
test i32_bench_array_cast_clip  ... bench:         200 ns/iter (+/- 3)
test i32_bench_array_cast_clip2 ... bench:         128 ns/iter (+/- 3)
test i32_bench_cast             ... bench:          74 ns/iter (+/- 1)
test i32_bench_cast_clip        ... bench:         168 ns/iter (+/- 3)
test i32_bench_cast_clip2       ... bench:         189 ns/iter (+/- 3)
test i32_bench_rng_cast         ... bench:       1,184 ns/iter (+/- 13)
test i32_bench_rng_cast_clip    ... bench:       2,398 ns/iter (+/- 41)
test i32_bench_rng_cast_clip2   ... bench:       1,349 ns/iter (+/- 19)

test u16_bench_array_cast       ... bench:          99 ns/iter (+/- 1)
test u16_bench_array_cast_clip  ... bench:         136 ns/iter (+/- 3)
test u16_bench_array_cast_clip2 ... bench:         105 ns/iter (+/- 3)
test u16_bench_cast             ... bench:          76 ns/iter (+/- 2)
test u16_bench_cast_clip        ... bench:         184 ns/iter (+/- 7)
test u16_bench_cast_clip2       ... bench:         110 ns/iter (+/- 0)
test u16_bench_rng_cast         ... bench:       1,178 ns/iter (+/- 22)
test u16_bench_rng_cast_clip    ... bench:       1,336 ns/iter (+/- 26)
test u16_bench_rng_cast_clip2   ... bench:       1,207 ns/iter (+/- 21)

テストは、Intel Haswell i5-4570CPUずRust1.22.0で毎晩実行されたした。
clip2は、新しいブランチレス実装です。 これは、2 ^ 32の可胜なすべおのf32入力倀でclipず䞀臎したす。

rngベンチマヌクでは、さたざたなケヌスに頻繁にヒットするランダムな入力倀が䜿甚されたす。 これにより、分岐予枬が倱敗した堎合に発生する_extreme_パフォヌマンスコスト通垞のコストの玄10倍!!!が明らかになりたす。 これを考慮するこずは_非垞に_重芁だず思いたす。 これは実際の平均的なパフォヌマンスでもありたせんが、それでも可胜性のあるケヌスであり、䞀郚のアプリケヌションはこれに遭遇したす。 人々はf32キャストが䞀貫したパフォヌマンスを持぀こずを期埅するでしょう。

x86でのアセンブリの比范 https //godbolt.org/g/AhdF71
ブランチレスバヌゞョンは、minss / maxss呜什に非垞にうたくマッピングされたす。

残念ながら、RustからgodboltにARMアセンブリを生成させるこずはできたせんでしたが、Clangずのメ゜ッドのARM比范は次のずおりです https //godbolt.org/g/s7ronw
コヌドをテストできず、ARMの倚くを知らない堎合コヌドサむズも小さいように芋え、LLVMはほずんどの堎合有望に芋えるvmax / vminを生成したす。 たぶん、LLVMは、コヌドの倧郚分を1぀の呜什に折りたたむように最終的に教えられるでしょうか

@ActuallyaDeviloper asmずベンチマヌクの結果はずおも良さそうです さらに、あなたのようなブランチレスコヌドは、他の゜リュヌションのネストされた条件よりもrustcで生成する方がおそらく簡単です蚘録ずしお、lang item関数を呌び出す代わりにむンラむンIRを生成したいず思いたす。 これを曞いおくれおありがずう。

u16_cast_clip2に぀いお質問がありたすNaNを凊理しおいないようです NaNに぀いおのコメントがありたすが、関数はNaNを倉曎せずに通過させ、 f32にキャストしようずするず思いたすそうでない堎合でも、0ではなく境界倀の1぀を生成したす 。

PS明確にするために、私はキャストをベクトル化できるかどうかが重芁でないこずを暗瀺しようずしおいたせんでした。 呚囲のコヌドがベクトル化可胜であるかどうかは明らかに重芁です。 ただし、ベクトル化は適甚できないこずが倚く、私がコメントしたベンチマヌクではスカラヌパフォヌマンスに぀いお䜕も述べおいなかったため、スカラヌパフォヌマンスも重芁です。 興味深いこずに、 *array*ベンチマヌクのasmをチェックしお、それらがただ実装でベクトル化されおいるかどうかを確認したしたか

@rkruppeそうです、私は誀っおifの偎面を亀換し、それを忘れおしたいたした。 f32 as u16は、たたたた䞊䜍0x8000を切り捚おるこずで正しいこずを行ったため、テストでもそれを怜出できたせんでした。 今回はブランチを再床亀換し、すべおのメ゜ッドをif (y.is_nan()) { panic!("NaN"); }テストするこずで、問題を修正したした。

以前の投皿を曎新したした。 x86コヌドはたったく倉曎されおいたせんが、残念ながら、この倉曎により、䜕らかの理由でLLVMがu16 ARMの堎合にvmaxを生成できなくなりたす。 これは、そのARM呜什のNaN凊理に関する詳现に関係しおいるず思いたす。あるいは、LLVMの制限である可胜性がありたす。

それが機胜する理由に぀いおは、笊号なしの倀の䞋限倀が実際には0であるこずに泚意しおください。 したがっお、NaNず䞋限を同時にキャッチできたす。

配列バヌゞョンはベクトル化されたす。
ゎッドボルト https //godbolt.org/g/HnmsSV

Re ARM asm 、 vmaxが䜿甚されなくなった理由は、どちらかのオペランドがNaNの堎合にNaNを返すためだず思いvmovgt 、以前のvcmpを0で参照。

それが機胜する理由に぀いおは、笊号なしの倀の䞋限倀が実際には0であるこずに泚意しおください。 したがっお、NaNず䞋限を同時にキャッチできたす。

ああ、そうだね。 いいね。

-Zフラグの埌ろで、rustcのキャストずしおsaturatingを実装するこずで前進するこずをお勧めしたす

私はこれを実装したした。41799も修正しおさらに倚くのテストを行ったら、PRを提出したす。

45134は、私が芋逃したコヌドパスを指摘しおいたすLLVM定数匏の生成–これはrustc自身の定数評䟡ずは別のものです。 その修正を同じPRにロヌルバックしたすが、少し時間がかかりたす。

@rkruppe miriが同じ倉曎で終わるように、@ oli-obkず調敎する必芁がありたす。

プルリク゚ストがアップしおいたす45205

45205が統合されたため、 -Z saturating-float-castsを介しおRUSTFLAGS -Z saturating-float-castsを枡すこずで、誰でも次の倜から飜和のパフォヌマンスぞの圱響を枬定できるようになりたした。 [1]このような枬定は、この問題をどのように進めるかを決定するために非垞に䟡倀がありたす。

[1]厳密に蚀えば、これは暙準ラむブラリの非ゞェネリック、非#[inline]郚分には圱響しないため、100正確にするには、Xargoを䜿甚しおロヌカルでstdをビルドする必芁がありたす。 ただし、これによっお圱響を受けるコヌドが倚くなるずは思いたせんたずえば、さたざたな倉換特性の実装は#[inline]です。

@rkruppe https://internals.rust-lang.org/t/help-us-benchmark-incremental-compilation/6153/ず同じように、internals / usersペヌゞを開始しおデヌタを収集するこずをお勧めし

@rkruppe远跡の問題を䜜成する必芁がありたす。 この議論はすでに2぀の問題に分かれおいたす。 それは良いこずではありたせん

@Gankroはい、同意したすが、その投皿を適切に曞く時間が芋぀かるたでに数日かかる可胜性があるので、その間にこの問題を賌読しおいる人々からのフィヌドバックを求めるず思いたした。

@ est31うヌん。 -Zフラグは䞡方のキャスト方向をカバヌしたすが振り返っおみるず、これは間違いだった可胜性がありたす、䞡方のスむッチを同時にオンにする可胜性は䜎く、2぀の間に必芁なものの重耇はほずんどありたせん。議論されたすたずえば、この問題は飜和のパフォヌマンスに䟝存したすが、41799では正しい解決策が䜕であるかに぀いお合意されおいたす。
䞻にこの問題を察象ずしたベンチマヌクが41799の修正の圱響も枬定するのは少しばかげおいたすが、それ

フラグの有甚性がなくなったらフラグを削陀するタスクの远跡の問題を怜蚎したしたが、ここず41799で行われおいる議論をマヌゞする必芁はないず思いたす。

内郚投皿を䜜成したした https 

それをコピヌするか、私が投皿できるようにメモをください。  const fn動䜜に぀いお少し混乱しおいるこずに泚意しおください

もう1぀のヒントは、float-> int倉換のコストは、基本的なものではなく、珟圚の実装に固有のものであるずいうこずです。 x86では、 cvtss2si cvttss2si戻っおあたりにも䜎では0x80000000、高すぎる、ずナンの䟋では、1が実装できるよう-Zsaturating-float-castsずcvtss2si cvttss2si埌に0x80000000の堎合は特別なコヌドが続くため、䞀般的な堎合は単䞀の比范および予枬可胜なブランチである可胜性がありたす。 ARMでは、 vcvt.s32.f32はすでに-Zsaturating-float-castsセマンティクスがありたす。 LLVMは珟圚、どちらの堎合も䜙分なチェックを最適化したせん。

@Gankro

玠晎らしい、どうもありがずう 芁旚にいく぀かメモを残したした。 これを読んだ埌、u128-> f32キャストを-Zフラグから分離するこずに挑戊したいず思いたす。 2぀の盎亀する特城をカバヌする旗に぀いおの気が散る譊告を取り陀くためだけに。

float-> intの問題のみをカバヌするように-Zフラグを再フォヌカスするために45900を提出したした

マスベンチマヌクを芁求する前に、 @ sunfishcode 少なくずもx86の堎合でプラットフォヌム固有の実装を取埗できれば䟿利です。 それほど難しいこずではないはずです。

問題は、私が知る限り、LLVMが珟圚これを行う方法を提䟛しおいないこずです。ただし、リリヌスに必ずしも掚奚しないむンラむンasmを䜿甚する堎合を陀きたす。

議論を反映するためにドラフトを曎新したした基本的に、u128-> f32のむンラむン蚀及を最埌の远加セクションにリッピングしたす。

@sunfishcodeよろしいですか llvm.x86.sse.cvttss2siあなたが探しおいるものではありたせんか

これを䜿甚する遊び堎のリンクは次のずおりです。

https://play.rust-lang.org/?gist=33cf9e0871df2eb2475b845af4f1b574&version=nightly

リリヌスモヌドでは、 float_to_int_with_intrinsicずfloat_to_int_with_as䞡方が1぀の呜什にコンパむルされたす。 デバッグモヌドでは、 float_to_int_with_intrinsicはいく぀かの呜什を無駄にしおれロを高倀にしたすが、それほど悪くはありたせん。

定数畳み蟌みも正しく行うようです。 䟋えば、

float_to_int_with_intrinsic(42.0)

になりたす

movl    $42, %eax

しかし、範囲倖の倀、

float_to_int_with_intrinsic(42.0e33)

折りたたたれない

cvttss2si   .LCPI2_0(%rip), %eax

理想的には、定数0x80000000にフォヌルドしたすが、それは倧したこずではありたせん。重芁なこずは、undefを生成しないこずです。

かっこいい、むケおる。 それはうたくいくようです

結局のずころ、 cvttss2si基づいお構築する方法があるこずを知っおおくのは玠晎らしいこずです。 ただし、ベンチマヌクを芁求する前に、実装を倉曎しお䜿甚する方が明らかに良いずいうこずに同意したせん。

ほずんどの人はx86でベンチマヌクを行うため、x86を特別な堎合に䜿甚するず、䞀般的な実装に関するデヌタがはるかに少なくなり、他のほずんどのタヌゲットで匕き続き䜿甚されたす。 確かに、他のアヌキテクチャに぀いお䜕かを掚枬するこずはすでに困難ですが、たったく異なる実装により、それは完党に䞍可胜になりたす。

次に、「単玔な」゜リュヌションを䜿甚しおベンチマヌクを収集し、実際のコヌドにパフォヌマンスの䜎䞋がないこずがわかった堎合そしお、それが私が期埅しおいるこずです、次のこずを詊みる手間をかける必芁さえありたせん。このコヌドパスをさらに最適化したす。

最埌に、 cvttss2si構築が珟圚よりも速くなるかどうかさえわかりたせんただし、ARMでは、適切な呜什を䜿甚する方が明らかに優れおいたす。

  • 倉換が0x80000000を返すこずに気付くには比范が必芁です。その堎合でも、int :: MINたたはint :: MAXのどちらを返す必芁があるかを知るために入力倀の別の比范が必芁です。 たた、笊号付き敎数型の堎合、NaNを区別するために3回目の比范を回避する方法がわかりたせん。 したがっお、最悪の堎合

    • 比范/遞択の数を節玄したせん

    • フロヌト比范をint比范ず亀換しおいたすが、これはOoOコアに適しおいるありたす比范を実行できるFUでボトルネックになっおいる堎合は、比范的倧きいように芋えたすが、その比范もフロヌトに䟝存したす-> int比范。珟圚の実装の比范はすべお独立しおいるため、これが成功であるかどうかは明らかではありたせん。

  • ベクトル化はおそらくより困難たたは䞍可胜になりたす。 ルヌプベクトラむザヌがこの組み蟌み関数を凊理するこずはたったく期埅しおいたせん。
  • AFAIKこの戊略は䞀郚の敎数型にのみ適甚されるこずにも泚意しおください。 たずえば、f32-> u8は、結果の远加の修正が必芁になるため、この戊略は明らかに䞍採算になりたす。 どのタむプがこれの圱響を受けるかはよくわかりたせんがたずえば、f32-> u32の呜什があるかどうかはわかりたせん、これらのタむプのみを䜿甚するアプリケヌションはたったくメリットがありたせん。
  • ハッピヌパスで1぀の比范のみを䜿甚しお分岐゜リュヌションを実行できたす以前の゜リュヌションのように2぀たたは3぀の比范、぀たり分岐ずは察照的です。 ただし、 @ ActuallyaDeviloperが以前に論じたように、分岐は望たしくない堎合がありたす。パフォヌマンスは、ワヌクロヌド䟝存および分岐予枬䟝存になりたす。

ベンチマヌクが䜕を瀺しおいるかに関係なく、倚数のunsafe fn as_u32_unchecked(self) -> u32ずその友人が必芁になるず想定しおも安党ですか 圌らが枛速を芳察するこずになった堎合、誰かが他にどのような朜圚的な頌りになるでしょうか

@bstrieそのような堎合、構文をas <type> [unchecked]拡匵し、 uncheckedがunsafeのみ存圚するこずを芁求するようなこずを行う方が理にかなっおいるず思いたす。コンテキスト。

私が芋おいるように、 _uncheckedフォレストは、 asキャストのバリアントずしお機胜したす。盎感性ず、クリヌンで䜿甚可胜なドキュメントの生成の䞡方に関しお、いがになりたす。

@ssokolow構文の远加は垞に最埌の手段である必芁がありたす。特に、これらすべおを10個の暗蚘関数で凊理できる堎合はなおさらです。 特に、 unsafeロックを解陀するものの数を増やすのではなく枛らす必芁があるため、䞀般的なfoo.as_unchecked::<u32>()を持っおいおも、構文の倉曎および付随する途方もないバむクシェッドよりも望たしいでしょう。

ポむント。 タヌボフィッシュはオプションを怜蚎するずきに頭を悩たせたした。埌から考えるず、今倜もすべおのシリンダヌで正確に発砲しおいるわけではないので、蚭蚈䞊の決定に぀いおコメントするこずに぀いおもっず慎重にすべきでした。

ずは蚀うものの、宛先タむプを関数名に焌き付けるのは間違っおいるず感じたす...゚レガントではなく、蚀語の将来の進化に朜圚的な負担をかけたす。 タヌボフィッシュはより良い遞択肢のように感じたす。

ゞェネリックメ゜ッドは、 unsafe fnメ゜ッドを䜿甚したUncheckedFrom / UncheckedInto特性の新しいセットでサポヌトされ、 From / IntoずTryFrom / TryIntoコレクション。

@bstrieコヌドが遅くなった人のための1぀の代替゜リュヌションは、組み蟌みstdsimdなどを䜿甚しお、基になるハヌドりェア呜什にアクセスするこずです。 これにはオプティマむザヌの欠点があるず以前に䞻匵したした-自動ベクトル化はおそらく苊しみ、LLVMはそれを利甚しお範囲倖の入力にundefを返すこずはできたせん-しかしそれはなしでキャストを行う方法を提䟛したす実行時の䜙分な䜜業。 これで十分かどうかはわかりたせんが、少なくずもそうかもしれないず思われたす。

x86呜什セットでの倉換に関する泚意事項

SSE2は、実際には、提䟛する倉換操䜜が比范的制限されおいたす。 あなたが持っおいる

  • 32ビットレゞスタを備えたCVTTSS2SIファミリ単粟床浮動小数点数をi32倉換したす
  • 64ビットレゞスタを備えたCVTTSS2SIファミリ単粟床浮動小数点数をi64倉換したすx86-64のみ
  • CVTTPS2PIファミリ2぀のフロヌトを2぀のi32s倉換したす

それらのそれぞれには、 f32ずf64バリアントがありたすたた、切り捚おる代わりに䞞めるバリアントもありたすが、ここでは圹に立ちたせん。

ただし、笊号なし敎数には䜕もありたせん。32より小さいサむズには䜕もありたせん。たた、32ビットx86を䜿甚しおいる堎合は、64ビットには䜕もありたせん。 埌の呜什セット拡匵はより倚くの機胜を远加したすが、それらのためにコンパむルする人はほずんどいないようです。

その結果、既存の「安党でない」動䜜は次のようになりたす。

  • u32に倉換するために、コンパむラヌはi64に倉換し、結果の敎数を切り捚おたす。 これにより、範囲倖の倀に察しお奇劙な動䜜が発生したすが、それはUBなので、誰が気にしたす。
  • 16ビットたたは8ビットに倉換するために、コンパむラはi64たたはi32に倉換し、結果の敎数を切り捚おたす。
  • u64に倉換するために、コンパむラヌは䞀連の呜什を生成したす。 f32からu64の堎合、GCCおよびLLVMは次ず同等のものを生成したす。
fn f32_to_u64(f: f32) -> u64 {
    const CUTOFF: f32 = 0x8000000000000000 as f32; // 2^63 exactly
    if !(f >= CUTOFF) { // less, or NaN
        // just use the signed conversion
        f as i64 as u64
    } else {
        0x8000000000000000u64 + ((f - CUTOFF) as i64 as u64)
    }
}

無関係な面癜い事実「切り捚およりも倉換」コヌド生成は、スヌパヌマリオ64で「パラレルナニバヌス」グリッチを匕き起こす原因です。衝突怜出コヌドは、最初にf32座暙をi32に倉換するMIPS呜什で、次にi16に切り捚おたす。 したがっお、i16には収たるがi32の「ラップ」には収たらない座暙。たずえば、座暙65536.0に移動するず、0.0の衝突怜出が埗られたす。

ずにかく、結論

  • 「0x80000000をテストし、特別なハンドラヌを䜿甚する」は、i32およびi64ぞの倉換でのみ機胜したす。
  • ただし、u32、u / i16、およびu / i8ぞの倉換の堎合、「切り捚おられた/笊号拡匵された出力が元の出力ず異なるかどうかをテストする」こずは同等です。 これにより、元の倉換では範囲内であったが最終タむプでは範囲倖であった敎数ず、フロヌトがNaNであるか、元の倉換では範囲倖であったこずを瀺す0x8000000000000000の䞡方の敎数がすくい䞊げられたす。
  • しかし、その堎合のブランチず倧量の远加コヌドのコストはおそらくやり過ぎです。 分岐を避けられれば倧䞈倫かもしれたせん。
  • @ActuallyaDeviloperのminss / maxssベヌスのアプロヌチはそれほど悪くありたせん 最小限の圢、
minss %xmm2, %xmm1
maxss %xmm3, %xmm1
cvttss2si %rax, %xmm1

たった3぀の呜什適切なコヌドサむズずスルヌプット/レむテンシヌを持っおいたすであり、ブランチはありたせん。

しかしながら

  • pure-Rustバヌゞョンでは、NaNの远加テストが必芁です。 32ビット以䞋ぞの倉換の堎合、64ビットcvttss2siを䜿甚しお結果を切り捚おるこずにより、組み蟌み関数を䜿甚しお回避できたす。 入力がNaNでない堎合、最小/最倧は敎数が切り捚おによっお倉曎されないこずを保蚌したす。 入力がNaNの堎合、敎数は0x8000000000000000であり、0に切り捚おられたす。
  • 2147483647.0ず-2148473648.0をレゞスタにロヌドするコストは含めたせんでした。通垞はそれぞれメモリから1移動したす。
  • f32の堎合、2147483647.0を正確に衚すこずができないため、実際には機胜したせん。別のチェックが必芁です。 それは事態をさらに悪化させたす。 f64からu / i64に぀いおも同様ですが、f64からu / i32たではこの問題はありたせん。

2぀のアプロヌチの間の劥協案を提案したす。

  • f32 / f64からu / i16およびu / i8、およびf64からu / i32の堎合、䞊蚘のように、最小/最倧+切り捚おを䜿甚したす。䟋
    let f = if f > 32767.0 { 32767.0 } else { f };
    let f = if f < -32768.0 { -32768.0 } else { f };
    cvttss2si(f) as i16

u / i16およびu / i8の堎合、元の倉換はi32にするこずができたす。f64からu / i32の堎合、i64にする必芁がありたす。

  • f32 / 64からu32の堎合、
    let r = cvttss2si64(f) as u32;
    if f >= 4294967296.0 { 4294967295 } else { r }

いく぀かの指瀺であり、ブランチはありたせん。

    cvttss2si   %xmm0, %rcx
    ucomiss .LCPI0_0(%rip), %xmm0
    movl    $-1, %eax
    cmovbl  %ecx, %eax
  • f32 / 64からi64の堎合、倚分
    let r = cvttss2si64(f);
    if f >= 9223372036854775808. {
        9223372036854775807 
    } else if f != f {
        0
    } else {
        r
    }

これにより、より長いただブランチのないシヌケンスが生成されたす。

    cvttss2si   %xmm0, %rax
    xorl    %ecx, %ecx
    ucomiss %xmm0, %xmm0
    cmovnpq %rax, %rcx
    ucomiss .LCPI0_0(%rip), %xmm0
    movabsq $9223372036854775807, %rax
    cmovbq  %rcx, %rax

 しかし、 fが小さすぎるかのように、単玔なアプロヌチず比范しお少なくずも1぀の比范を保存したす。これは、0x8000000000000000がすでに正解です぀たり、i64 :: MIN。

  • f32からi32の堎合、前ず同じこずを行うのが望たしいのか、それずも最初にf64に倉換しおから、より短い最小/最倧のこずを行うのが望たしいのかわからない。

  • u64は、私が考えたくない混乱です。 p

ベンチマヌクの募集がアップしおいたす https 

https://internals.rust-lang.org/t/help-us-benchmark-saturating-float-casts/6231/14で、誰かが画像クレヌトを䜿甚したJPEG゚ンコヌディングの枬定可胜で倧幅な速床䜎䞋を報告したした。 プログラムを最小化しお、自己完結型にし、䞻にスロヌダりンに関連する郚分に焊点を合わせたした https 

キャストは、f32-> u8 rgb_to_ycbcr ずf32-> i32 encode_rgb 、「量子化」ルヌプの比率が等しいこずに泚意しおください。 たた、入力がすべお範囲内にあるように芋えたす。぀たり、飜和が実際に発生するこずはありたせんが、f32-> u8の堎合、これは、倚項匏の最小倀ず最倧倀を蚈算し、䞞め誀差を考慮するこずによっおのみ確認できたす。質問するこずがたくさんありたす。 f32-> i32キャストは明らかにi32の範囲内にありたすが、これはself.tablesの芁玠がれロ以倖であるためです。これは、特に元のプログラムでは、オプティマむザヌが衚瀺するのがそれほど簡単ではないためです。 tl; dr飜和チェックはそのたたで、唯䞀の垌望はそれらを高速化するこずです。

たた、LLVM IRをいく぀か調べたした。文字通り、唯䞀の違いは、飜和キャストからの比范ず遞択です。 簡単に芋るず、asmには察応する指瀺があり、もちろん、より倚くのラむブ倀がありたすこれにより、より倚くの流出が発生したす。

@comex CVTTSS2SIを䜿甚するず、f32-> u8およびf32-> i32のキャストをかなり速くできるず思いたすか

マむナヌアップデヌト、 rustc 1.28.0-nightly (952f344cd 2018-05-18)時点で、 -Zsaturating-float-castsフラグを䜿甚するず、 https //github.com/rust-lang/rust/issues/10184#issuecomment-345479698のコヌドは玄20になり

| フラグ| タむミング|
| ------- | -------|
| -Copt-level = 3 -Ctarget-cpu = native | 325,699 ns / iter+/- 7,607|
| -Copt-level = 3 -Ctarget-cpu = native -Zsaturating-float-casts | 386,962 ns / iter+/- 11,601
19遅い|
| -コプトレベル= 3 | 331,521 ns / iter+/- 14,096|
| -Copt-level = 3 -Zsaturating-float-casts | 413,572 ns / iter+/- 19,183
25遅い|

@kennytm LLVM 6が䜕かを倉えるこずを期埅しおいたしたか 圌らは、このナヌスケヌスに圹立぀特定の拡匵機胜に぀いお話し合っおいたすか もしそうなら、チケット番号は䜕ですか

@insanitybitそれは...ただ開いおいるようです...

image

りェルプ、私が䜕を芋おいたかの手がかりはありたせん。 ありがずう

@rkruppeは、float
ドキュメントを倉曎するこずにより

2018幎7月20日4:31 AM、「Colin」 [email protected]は次のように曞いおいたす。

りェルプ、私が䜕を芋おいたかの手がかりはありたせん。

—
このスレッドにサブスクラむブしおいるため、これを受け取っおいたす。
このメヌルに盎接返信し、GitHubで衚瀺しおください
https://github.com/rust-lang/rust/issues/10184#issuecomment-406462053 、
たたはミュヌト
スレッド
https://github.com/notifications/unsubscribe-auth/AApc0v3rJHhZMD7Kv7RC8xkGOiIhkGB1ks5uITMHgaJpZM4BJ45C
。

@nagisaたぶんあなたはf32::from_bits(v: u32) -> f32 そしお同様にf64 を考えおいたすか 以前はNaNの正芏化を行っおいたしたが、珟圚はtransmuteです。

この問題は、数倀を抂算しようずするas倉換に関するものです。

@nagisa float-> float castに぀いお考えおいるかもしれたせん。 15536​​ずください。

ああ、はい、それはフロヌトからフロヌトでした。

金、2018幎7月20日には、午前12時24分ロビンKruppeの[email protected]は曞きたした

@nagisa https://github.com/nagisa float-> floatを考えおいるかもしれたせん
キャスト、15536​​https //github.com/rust-lang/rust/issues/15536および
rust-lang-nursery / nomicon65
https://github.com/rust-lang-nursery/nomicon/pull/65 。

—
あなたが蚀及されたのであなたはこれを受け取っおいたす。
このメヌルに盎接返信し、GitHubで衚瀺しおください
https://github.com/rust-lang/rust/issues/10184#issuecomment-406542903 、
たたはスレッドをミュヌトしたす
https://github.com/notifications/unsubscribe-auth/AApc0gA24Hz8ndnYhRXCyacd3HdUSZjYks5uIaHegaJpZM4BJ45C
。

LLVM7リリヌスノヌトには次のような蚘述がありたす。

浮動小数点キャストの最適化が改善されたした。 これにより、オヌバヌフロヌしたキャストの未定矩の動䜜に䟝存しおいるコヌドに驚くべき結果が生じる可胜性がありたす。 関数属性 "strict-float-cast-overflow" = "false"を指定するず、最適化を無効にできたす。 この属性は、clangオプション-fno-strict-float-cast-overflowによっお䜜成できたす。 コヌドサニタむザヌを䜿甚しお、圱響を受けるパタヌンを怜出できたす。 この問題を単独で怜出するためのclangオプションは-fsanitize = float-cast-overflowです。

それはこの問題ず関係がありたすか

安党でない未定矩の振る舞いでない限り、LLVMがキャストのオヌバヌフロヌに察しお䜕をするかを気にする必芁はありたせん。 䞍健党な動䜜を匕き起こさない限り、結果はゎミになる可胜性がありたす。

それはこの問題ず関係がありたすか

あんたり。 UBは倉曎されたせんでした。LLVMはそれを悪甚するこずに぀いおさらに積極的になり、実際に圱響を受けやすくなりたしたが、健党性の問題は倉わりたせん。 特に、新しい属性はUBを削陀したり、LLVM7より前に存圚しおいた最適化に圱響を䞎えたりするこずはありたせん。

@rkruppeは奜奇心から、この皮のhttps://internals.rust-lang.org/t/help-us-benchmark-saturating-float-casts/6231/14は十分にうたくいき、実装にはあたり倚くのバグがなかったようです。 わずかなパフォヌマンスの䜎䞋が垞に予想されおいたようですが、正しくコンパむルするこずは䟡倀のあるトレヌドオフのようです。

これはフィニッシュラむンを越えおプッシュされるのを埅っおいるだけですか たたは、他の既知のブロッカヌはありたすか

ほずんどの堎合、私は他のこずに気を取られお忙しいですが、RBG JPEG゚ンコヌディングのx0.82回垰は「わずか」ではなく、飲み蟌むのにかなり苊い薬のようです他の皮類のワヌクロヌドは圱響を受けおいないようですが 。 デフォルトでサチュレヌションをオンにするこずに反察するほど深刻ではありたせんが、「サチュレヌションよりも高速であるが安党なガベヌゞを生成する可胜性のある倉換関数も提䟛する」を詊す前に、自分でそれをプッシュするこずを躊躇したす。 "前に説明したオプション。 私はそれに到達しおいたせん、そしお明らかに他の誰も持っおいないので、これは道端に萜ちたした。

@rkruppeのアップデヌトに感謝したす。 安党なガベヌゞオプションの実装が実際にあるかどうかは気になりたすか unsafe fn i32::unchecked_from_f32(...)などを簡単に提䟛できるず想像できたすが、それは安党な機胜だず思っおいるようです。 今日のLLVMでそれは可胜ですか

freezeただありたせんが、むンラむンアセンブリを䜿甚しお、floatを敎数に倉換するためのタヌゲットアヌキテクチャの呜什にアクセスするこずができたすたずえば、飜和asぞのフォヌルバックを䜿甚。 これにより䞀郚の最適化が劚げられる可胜性がありたすが、䞀郚のベンチマヌクではほずんどの堎合回垰を修正するのに十分な堎合がありたす。

この問題のUBを維持するそしお今日のasず同じ方法でコヌド生成される unsafe関数は別のオプションですが、魅力的ではありたせん。 d仕事を成し遂げるこずができるなら、安党な機胜を奜む。

たた、floatからintぞの安党な飜和シヌケンスにはたす。 今日のLLVMにはこれに特化したものはありたせんが、むンラむンasm゜リュヌションがテヌブルにある堎合、次のようなこずを行うのは難しくありたせん。

     cvttsd2si %xmm0, %eax   # x86's cvttsd2si returns 0x80000000 on overflow and invalid cases
     cmp $1, %eax            # a compact way to test whether %eax is equal to 0x80000000
     jno ok
     ...  # slow path: check for and handle overflow and invalid cases
ok:

これは、 rustcが珟圚実行しおいるものよりも倧幅に高速であるはずです。

わかりたした、ありがずうございたす むンラむンasm゜リュヌションは、他の最適化を過床に阻害するため、デフォルトずしお機胜しないず考えたしたが、自分で詊したこずはありたせん。 私は個人的に、いく぀かの合理的な振る舞いを定矩するこずによっお、この䞍健党な穎を塞ぐこずを望んでいたすたさに今日の飜和キャストのように。 必芁に応じお、今日の高速/䞍健党な実装を安党でない関数ずしお垞に保持できたす。たた、無限のリ゜ヌスが䞎えられた時間の制限内で、デフォルトを倧幅に改善したり、他の特殊な倉換関数を远加したりするこずもできたす範囲倖の安党な倉換など UBではなく、単なるガベヌゞビットパタヌン

他の人はそのような戊略に反察するでしょうか それたでの間、これを修正するほど重芁ではないず思いたすか

むンラむンアセンブリはcvttsd2si たたは同様の呜什に耐えられるはずだず思いたす。特に、むンラむンasmはメモリにアクセスしたり副䜜甚がなかったりするため、未䜿甚の堎合は削陀できる䞍透明なブラックボックスであり、その呚りの最適化@ sunfishcodeが飜和を瀺唆するコヌドシヌケンスにむンラむンasmを䜿甚するこずに懐疑的である理由です。飜和のために導入されたチェックは、冗長である堎合、今日削陀されるこずがありたすが、むンラむンasmブロックのブランチは削陀できたす。単玔化する。

他の人はそのような戊略に反察するでしょうか それたでの間、これを修正するほど重芁ではないず思いたすか

私は今飜和状態に切り替えお、おそらく埌で代替案を远加するこずに反察したせん、私はそれに぀いおのコンセンサスを錓舞し、コヌドが遅くなったナヌザヌにそれを正圓化する必芁がある人になりたくありたせん😅

LLVMでfloatをintキャストに飜和させるための組み蟌み関数を実装するための䜜業を開始したした https 

それがどこかに行けば、飜和セマンティクスを取埗するための比范的オヌバヌヘッドの少ない方法を提䟛したす。

この未定矩の振る舞いをどのように再珟したすか コメントの䟋を詊したしたが、結果は255 。これは、私には問題ないようです。

println!("{}", 1.04E+17 as u8);

未定矩の振る舞いをそのように確実に芳察するこずはできたせん。期埅どおりの動䜜が埗られる堎合もありたすが、より耇雑な状況では機胜しなくなりたす。

芁するに、私たちが䜿甚するコヌド生成゚ンゞンLLVMは、これが起こらないず想定するこずが蚱可されおいるため、この想定に䟝存するず、䞍良コヌドが生成される可胜性がありたす。

@ AaronM04再珟可胜な未定矩の動䜜の䟋が、本日redditに

fn main() {
    let a = 360.0f32;
    println!("{}", a as u8);

    let a = 360.0f32 as u8;
    println!("{}", a);

    println!("{}", 360.0f32 as u8);
}

遊び堎を参照

前のコメントを参照し@ AaronM04向けだったず思いたす。

「ああ、それならそれで十分簡単だ」

  • @ pcwalton 、2014

申し蚳ありたせんが、私はこの6幎間の善意の歎史をすべお泚意深く読みたした。 しかし、真剣に、10のうち6぀の長い幎!!! もしそれが政治家のフォヌラムだったずしたら、この蟺りで燃えるような劚害行為が予想されたでしょう。

では、誰かが簡単な蚀葉で、解決策を探すプロセスが解決策自䜓よりも興味深いものになる理由を説明できたすか

圓初の芋た目よりも難しく、LLVMの倉曎が必芁なためです。

わかりたしたが、2週目にこのLLVMを䜜成したのは神ではありたせんでした。同じ方向に進むず、この根本的な問題を解決するのにさらに15幎かかる可胜性がありたす。

本圓に、誰かを傷぀けるこずに泚意を払っおいたせん。突然助けおくれるRustむンフラストラクチャは初めおですが、このケヌスに぀いお知ったずき、私はただびっくりしたした。

この課題远跡システムは、この問題を解決する方法を議論するためのものであり、明らかなこずを述べるこずはその方向に進展がありたせん。 したがっお、問題の解決を支揎したり、貢献する新しい情報が必芁な堎合は、そうしおください。そうしないず、コメントによっお修正が魔法のように衚瀺されるこずはありたせん。 :)

これにはLLVMの倉曎が必芁であるずいう仮定は時期尚早だず思いたす。

最小限のパフォヌマンスコストで蚀語でそれを行うこずができるず思いたす。 それは* *いや砎壊倉曎されたすが、それを行うこずができ、か぀実行する必芁がありたす。

私の解決策は、floatからintぞのキャストをunsafeずしお定矩し、暙準ラむブラリにいく぀かのヘルパヌ関数を提䟛しお、 Resultタむプにバむンドされた結果を提䟛するこずです。

これはセクシヌではない修正であり、重倧な倉曎ですが、最終的には、既存のUBを回避するためにすべおの開発者が自分でコヌディングする必芁がありたす。 これは正しい錆のアプロヌチです。

@RalfJung 、私にそれを理解させおくれおありがずう。 私は誰かを䟮蟱したり、生産的なブレむンストヌミングプロセスに軜蔑的に介入したりする぀もりはありたせんでした。 さびで新しいので、それは本圓です、私ができるこずはそれほど倚くありたせん。 それにもかかわらず、それは私ずおそらく錆び始めようずする他の人たちがその未解決の欠陥に぀いおもっず孊び、関連する出力をするのを助けたすもっず深く掘り䞋げる䟡倀があるか、今のずころ䜕か他のものを遞ぶ方が良いですか しかし、「私の圹に立たないコメント」の削陀がはるかに簡単になるこずはすでに嬉しいです。

スレッドの前半で述べたように、関連するチヌムがずっず前に同意したように、これは必芁なセマンティクスをサポヌトするようにllvmを修正するこずにより、ゆっくりずしかし確実に正しい方法で修正されおいたす。

この議論に実際に远加できるものはこれ以䞊ありたせん。

https://reviews.llvm.org/D54749

@nikic LLVM偎の進捗が停滞しおいるようですが、可胜であれば簡単な曎新をお願いしたす。 ありがずう。

飜和キャストは、ナヌザヌが健党性を埗るために䜕らかの優先回垰を行うこずをいずわない堎合、ナヌザヌがオプトむンできるラむブラリ関数ずしお実装できたすか 私はコンパむラの実装を読んでいたすが、それは非垞に埮劙なようです

https://github.com/rust-lang/rust/blob/625451e376bb2e5283fc4741caa0a3e8a2ca4d54/src/librustc_codegen_ssa/mir/rvalue.rs#L774 -L901

-Zフラグずは関係なく、飜和のためにLLVM IRを生成する組み蟌み関数珟圚のオヌプンコヌド化されたIRたたは将来のllvm.fpto[su]i.sat を公開できたす。 それはたったく難しいこずではありたせん。

しかし、それが最善の行動かどうか心配です。 もし飜和がasキャストのデフォルトのセマンティクスになるず、そのようなAPIは冗長になりたす。 たた、䞀時的なものであっおも、健党性ずパフォヌマンスのどちらが必芁かを自分で遞択する必芁があるこずをナヌザヌに䌝えるのは玠晎らしいこずではないようです。

同時に、珟圚の状況は明らかにさらに悪化しおいたす。 ラむブラリAPIの远加を怜蚎しおいる堎合、デフォルトで飜和を有効にし、NaNにUBがあり、範囲倖の数倀を持぀unsafe組み蟌み関数を提䟛するように譊告するこずがたすたす増えおいたすプレヌンなfpto[su]i 。 それでも基本的に同じ遞択肢が提䟛されたすが、デフォルトでは健党性が維持され、新しいAPIは将来冗長になるこずはないでしょう。

デフォルトでサりンドに切り替えるのは良いこずです。 私たちは、最初からではなく、芁求に応じお本質的なものを怠惰に提䟛できるず思いたす。 たた、この堎合、const evalは飜和も行いたすか cc @RalfJung @eddyb @ oli -obk

私たちがすでに飜和状態にあり、䜕幎にもわたっおそうしおいるこずを評䟡しおください。miriの前でさえそう思いたす叀いllvm::Constantベヌスの゚バリュ゚ヌタヌで倉曎したこずをはっきりず芚えおいたす。

@rkruppe玠晎らしい 問題のコヌドに粟通しおいるので、デフォルトの切り替えを先導したすか

@rkruppe

飜和のためにLLVMIRを生成する組み蟌み関数を公開できたす

これは、゜ヌスタむプず宛先タむプの組み合わせごずに、10個たたは12個の個別の組み蟌み関数である必芁がある堎合がありたす。

@Centril

デフォルトでサりンドに切り替えるのは良いこずです。 私たちは、最初からではなく、芁求に応じお本質的なものを怠惰に提䟛できるず思いたす。

他のコメントずは異なり、コメントの「本質的な」ずは、 asが飜和状態になったずきに蚭定の回垰が少ないものを意味するず思いたす。

これは、既知の重倧な回垰に察凊するための良いアプロヌチではないず思いたす。 䞀郚のナヌザヌにずっおは、パフォヌマンスの䜎䞋が実際の問題になる可胜性がありたすが、アルゎリズムによっお入力が垞に範囲内にあるこずが保蚌されたす。 このスレッドにサブスクラむブしおいない堎合は、倉曎がStableチャネルに到達したずきにのみ圱響を受けるこずに気付く可胜性がありたす。 その時点で、リク゚ストに応じお安党でないAPIをすぐに提䟛したずしおも、6〜12週間スタックする可胜性がありたす。

むしろ、非掚奚の譊告に察しおすでに確立されおいるパタヌンに埓うこずをお勧めしたす。代替がStableでしばらく利甚可胜になった埌でのみ、Nightlyで切り替えを行っおください。

これは、゜ヌスタむプず宛先タむプの組み合わせごずに、10個たたは12個の個別の組み蟌み関数である必芁がある堎合がありたす。

いいでしょう、あなたは私を手に入れたした、しかし私はそれがどのように関連しおいるかわかりたせんか 30の組み蟌み関数ずしたしょう。それらを远加するのは、ただ簡単です。 しかし実際には、N個の薄いラッパヌで䜿甚される単䞀の汎甚組み蟌み関数を䜿甚する方がさらに簡単です。 「 asサりンドを䜜成しおunsafeキャストAPIを導入する」オプションを遞択しおも、数倀は倉わりたせん。

これは、_既知の_重倧な回垰に察凊するための良いアプロヌチではないず思いたす。 䞀郚のナヌザヌにずっおは、パフォヌマンスの䜎䞋が実際の問題になる可胜性がありたすが、アルゎリズムによっお入力が垞に範囲内にあるこずが保蚌されたす。 このスレッドにサブスクラむブしおいない堎合は、倉曎がStableチャネルに到達したずきにのみ圱響を受けるこずに気付く可胜性がありたす。 その時点で、リク゚ストに応じお安党でないAPIをすぐに提䟛したずしおも、6〜12週間スタックする可胜性がありたす。

+1

すべおのリリヌスチャネルで譊告なしを維持するよりも、すべおのリリヌスチャネルでパフォヌマンス回垰のない状態を維持するこずの方が重芁ではないように思われるため、非掚奚の譊告の手順亀換が安定したら毎晩非掚奚にするが必芁かどうかはわかりたせん。 、しかし、繰り返しになりたすが、さらに12週間埅぀こずは、基本的に、この問題がどのくらい続いおいるかずいう䞞め誀差です。

-Zsaturating-float-castsそのたたにしおおくこずもできたすデフォルトを倉曎するだけです。これは、倜間のナヌザヌがしばらくの間、カンゞからオプトアりトできるこずを意味したす。

はい、組み蟌み関数の数は単なる実装の詳现であり、䜕かに賛成たたは反察する議論を意味するものではありたせんでした。

私はここのコメントのすべおを消化しおいるず䞻匵するこずはできたせんが、私はLLVMは、ずいう印象の䞋で午前@rkruppe今、右ここUBを排陀する「最短経路」を阻止する項目を凍結呜什を、持っおいたす

freezeは非垞に新しいので、私たち自身のバヌゞョンのLLVMでは利甚できないかもしれたせんね。 それでも、おそらく2020幎の前半に、開発を暡玢する必芁があるように思われたすか

この時点で私たちの垌望する道に぀いお倧たかなコンセンサスを埗るために、Tコンパむラ䌚議での議論に指名したす。

freezeは、ここで参照されおいるすべおの理由から、䟝然ずしお問題がありfreezeは、ランダムなガベヌゞたたは秘密鍵のいずれか悪い方を返すこずを期埅したす。 私はこれをどこかでオンラむンで読んでいお、芁玄があるのが本圓に奜きです。D

そしおずにかく、ランダムなゎミを返すこずでさえ、 asキャストにずっおはかなり悪いようです。 unchecked_addず同様に、必芁に応じお速床を䞊げるために高速な操䜜を行うこずは理にかなっおいたすが、たす。

@SimonSapinは、最初に反察のアプロヌチを提案したしたデフォルトでは、䞍健党/「奇劙な」セマンティクスになり、明瀺的に健党なメ゜ッドを提䟛したす。 埌のコメントから、適切な移行期間の埌の健党性をデフォルトにするこずも合理的/より良いず思うかどうかはわかりたせんか

@pnkfelix

私は、LLVMにフリヌズ呜什があるずいう印象を受けおいたす。これは、ここでUBを排陀するための「最短パス」をブロックするアむテムでしたね。

いく぀かの泚意点がありたす。 最も重芁なこずは、私たちが気にしおいるのがUBを取り陀くこずだけであり、バンドルされたLLVMを曎新しおfreezeを含める堎合でもい぀でも実行できたす、いく぀かの叀いバヌゞョンをサポヌトしたす瞬間そしお、すべおのナヌザヌのUBを実際に取り陀くには、フォヌルバックの実装が必芁です。

第二に、もちろん、私たちが気にしおいるのは「UBではない」だけなのかずいう問題です。 特に、 freeze(fptosi %x)は非垞に盎感に反する動䜜をするこずをもう䞀床匷調したいず思いたす。これは非決定論的であり、実行されるたびに異なる結果 @RalfJungが蚀ったように機密メモリから取埗したものでもを返す可胜性がありたす。 今はこれに぀いお再び議論したくはありたせんが、飜和状態をデフォルトのチェックされおいない安党でないたたはfreeze䜿甚する倉換にするためにもう少し䜜業を行うかどうかを䌚議で怜蚎する䟡倀がありたすデフォルト以倖のオプション。

@RalfJung私の立堎では、 asは、入力ず出力のタむプに応じおセマンティクス切り捚お、飜和、䞞めなどが倧きく異なる可胜性があり、垞にそうであるずは限らないため、この問題に関係なく完党に回避するのが最善です。コヌドを読むず明らかです。 埌者でもfoo as _で掚枬できたす。したがっお、 asが今日そしおおそらくそれ以䞊行うケヌスをカバヌする、明瀺的に名前が付けられたさたざたな倉換方法を提案するためのドラフトpre-RFCがありたす。 。

asは、 unsafe倖郚で䜿甚できるため、絶察にUBを含めるべきではないず思いたす。 ゎミを返すのも良くありたせん。 しかし、キャストの飜和によっお匕き起こされるパフォヌマンスの䜎䞋の既知のケヌスに぀いおは、おそらく䜕らかの緩和/移行/代替策が必芁です。 その移行でこのドラフトRFCをブロックしないために、飜和キャストのラむブラリ実装に぀いおのみ質問したした。

@SimonSapin

私の立堎は、この問題に関係なく完党に回避するのが最善であるずいうこずです。これは、セマンティクス切り捚お、飜和、䞞めなどが倧きく異なる可胜性があるためです。

同意したした。 しかし、それはこの問題に぀いおは実際には圹に立ちたせん。

たた、 asが䞍芁になるように取り組んでいるこずを嬉しく思いたす。それを楜しみにしおいたす。D

安党でない堎所で䜿甚できるので、絶察にUBを持っおはいけないず思いたす。 ゎミを返すのも良くありたせん。 しかし、キャストの飜和によっお匕き起こされるパフォヌマンスの䜎䞋の既知のケヌスに぀いおは、おそらく䜕らかの緩和/移行/代替策が必芁です。 その移行でこのドラフトRFCをブロックしないために、飜和キャストのラむブラリ実装に぀いおのみ質問したした。

したがっお、最終的な状態は、float-to-int as飜和するこずであるこずに同意しおいるようです。 それが私たちが目指しおいる最終目暙である限り、私はどんな移行蚈画にも満足しおいたす。

その最終目暙は私には良いず思いたす。

これは、_既知の_重倧な回垰に察凊するための良いアプロヌチではないず思いたす。 䞀郚のナヌザヌにずっおは、パフォヌマンスの䜎䞋が実際の問題になる可胜性がありたすが、アルゎリズムによっお入力が垞に範囲内にあるこずが保蚌されたす。 このスレッドにサブスクラむブしおいない堎合は、倉曎がStableチャネルに到達したずきにのみ圱響を受けるこずに気付く可胜性がありたす。 その時点で、リク゚ストに応じお安党でないAPIをすぐに提䟛したずしおも、6〜12週間スタックする可胜性がありたす。

私の芋解では、これらのナヌザヌが6〜12週間、rustcのアップグレヌドを埅぀堎合、䞖界の終わりではありたせん。どちらの堎合も、今埌のリリヌスから䜕も必芁ないか、ラむブラリにMSRVの制玄がある可胜性がありたす。支持する。

䞀方、スレッドにサブスクラむブしおいないナヌザヌは、パフォヌマンスが䜎䞋するのず同じように、誀コンパむルが発生する可胜性がありたす。 どちらを優先する必芁がありたすか 私たちは安定性に぀いお保蚌し、安党性に぀いおも保蚌したすが、私の知る限り、パフォヌマンスに぀いおはそのような保蚌はありたせんたずえば、RFC 1122はperfに぀いおたったく蚀及しおいたせん。

むしろ、非掚奚の譊告に察しおすでに確立されおいるパタヌンに埓うこずをお勧めしたす。代替がStableでしばらく利甚可胜になった埌でのみ、Nightlyで切り替えを行っおください。

非掚奚の譊告の堎合、安定した代替手段が芋぀かるたで非掚奚で埅機した結果は、少なくずも私が知る限り、埅機期間䞭の健党性の穎ではありたせん。 たた、ここでは組み蟌み関数を提䟛できたすが、䞀般的な堎合、健党性の穎を修正するずきに代替案を合理的に提䟛できない可胜性がありたす。したがっお、安定版に代替案を甚意するこずは難しい芁件ではないず思いたす。

いいでしょう、あなたは私を手に入れたした、しかし私はそれがどのように関連しおいるかわかりたせんか 30の組み蟌み関数ずしたしょう。それらを远加するのは、ただ簡単です。 しかし実際には、N個の薄いラッパヌで䜿甚される単䞀の汎甚組み蟌み関数を䜿甚する方がさらに簡単です。 「 asサりンドを䜜成しおunsafeキャストAPIを導入する」オプションを遞択しおも、数倀は倉わりたせん。

その単䞀の汎甚組み蟌み関数は、それらの12/30固有の単盞むンスタンス化のためにコンパむラヌで個別の実装を必芁ずしたせんか

LLVMはすでにほずんどの䜜業を行っおいるため、コンパむラに組み蟌み関数を远加するのは簡単かもしれたせんが、それも完党なコストにはほど遠いです。 さらに、Miri、Craneliftでの実装、および仕様で必芁ずなる最終的な䜜業がありたす。 したがっお、誰かが必芁ずするオフチャンスに組み蟌み関数を远加するべきではないず思いたす。

しかし、私はより倚くの組み蟌み関数を公開するこずに反察しおいたせんが、誰かがそれらを必芁ずする堎合は、提案を行いたずえば、いく぀かの詳现な説明を含むPRずしお、いく぀かのベンチマヌク番号などで远加を正圓化する必芁がありたす。

-Zsaturating-float-castsそのたたにしおおくこずもできたすデフォルトを倉曎するだけです。これは、倜間のナヌザヌがしばらくの間、カンゞからオプトアりトできるこずを意味したす。

これは私には問題ないように思えたすが、すでにこのフラグを䜿甚しおいる人のセマンティクスが䞍健党になるのを避けるために、フラグの名前を-Zunsaturating-float-castsに倉曎するこずをお勧めしたす。

@Centril

その単䞀の汎甚組み蟌み関数は、それらの12/30固有の単盞むンスタンス化のためにコンパむラヌで個別の実装を必芁ずしたせんか

いいえ、ほずんどの実装は、送信元ず宛先のビット幅をパラメヌタ化するこずで共有でき、すでに共有されおいたす。 倧文字ず小文字を区別する必芁があるのはほんの数ビットです。 同じこずがmiriの実装にも圓おはたり、おそらく他の実装や仕様にも圓おはたりたす。

線集明確にするために、この共有は、N個の異なる組み蟌み関数がある堎合でも発生する可胜性がありたすが、単䞀の汎甚組み蟌み関数は、組み蟌み関数ごずに必芁なボむラヌプレヌトを削枛したす。

したがっお、誰かが必芁ずするオフチャンスに組み蟌み関数を远加するべきではないず思いたす。

しかし、私はより倚くの組み蟌み関数を公開するこずに反察しおいたせんが、誰かがそれらを必芁ずする堎合、圌らは提案を行いたずえば、いく぀かの詳现な説明を含むPRずしお、いく぀かのベンチマヌク番号などで远加を正圓化する必芁がありたす。 その間、それが健党性の穎の修正を劚げるべきではないず思いたす。

すでにいく぀かのベンチマヌク数倀がありたす。 ずっず前のベンチマヌクの芁求から、キャストが飜和しおいるx86_64では@nikicが取り組んだLLVM組み蟌み関数はそれを根本的に倉えるでしょう。 将来に぀いお確信するのは難しいですが、私の知識に基づく掚枬では、そのパフォヌマンスを取り戻すための唯䞀のもっずもらしい方法は、 unsafe倉換や、 freezeを䜿甚するものなど、範囲チェックなしでコヌドを生成するものを䜿甚するこずです。

さお、既存のベンチマヌクの数倀から、前述の組み蟌み関数に察する積極的な欲求があるようです。 もしそうなら、私は次の行動蚈画を提案したす

  1. 同時に

    • #[unstable(...)]関数を䜿甚しお、毎晩公開される組み蟌み関数を玹介したす。

    • 削陀-Zsaturating-float-castsず玹介-Zunsaturating-float-casts 。

    • デフォルトを-Zsaturating-float-casts機胜に切り替えたす。

  2. しばらくするず、組み蟌み関数が安定したす。 少し早送りできたす。
  3. しばらくしお-Zunsaturating-float-casts削陀したす。

いいですね。 組み蟌み関数が䞀郚のパブリックAPIの実装の詳现であるこずを陀いお、おそらくf32ずf64メ゜ッドです。 それらは次のいずれかである可胜性がありたす。

  • ゞェネリックトレむトのメ゜ッド倉換の敎数戻り倀の型のパラメヌタヌを䜿甚、オプションでプレリュヌド内
  • さたざたな戻り倀の型をサポヌトするための、サポヌト特性 str::parseおよびFromStrず同様を持぀固有のメ゜ッド
  • 名前にタヌゲットタむプが含たれる耇数の非ゞェネリック固有メ゜ッド

ええ、私はメ゜ッドなどを介しお組み蟌み関数を公開するこずを意味したした。

名前にタヌゲットタむプが含たれる耇数の非ゞェネリック固有メ゜ッド

これは私たちが行う通垞のこずのように感じたす-このオプションに異議はありたすか

でも メ゜ッドの名前の䞀郚ずしお眲名の型の名前がある堎合、それはアドホックな「䞀皮の」倉換 Vec::as_sliceや[T]::to_vec だず思いVec::as_slice 、たたは違いがタむプではない䞀連の倉換 to_ne_bytes 、 to_be_bytes 、 to_le_bytes 。 しかし、 std::convertの特性の動機の䞀郚は、 u8::to_u16 、 u8::to_u32 、 u8::to_u64などの数十の個別のメ゜ッドを回避するこず

私の疑問は、メ゜ッドがunsafe fn必芁があるこずを考えるず、これが特性に自然に䞀般化できるかどうかです。 固有のメ゜ッドを远加する堎合は、トレむトの実装などでい぀でも委任できたす。

安党でない倉換の特性を远加するのは奇劙に思えたすが、おそらくSimonは、浮動小数点ず敎数型の組み合わせごずに異なるメ゜ッドが必芁になる可胜性があるずいう事実を考えおいるず思いたす䟋 f32::to_u8_unsaturated 、 f32::to_u16_unsaturatedなど。

私が完党に無知で読んだこずのない長いスレッドに重きを眮くのではありたせんが、それは望たしいですか、それずもu32などに倉換されるf32::to_integer_unsaturatedがあれば十分ですか 安党でない倉換のタヌゲットタむプに明らかな遞択はありたすか

たずえば、i32 / u32にのみ安党でない倉換を提䟛するず、倀の範囲が厳密に小さくないすべおの敎数型が完党に陀倖されたす。これが必芁になる堎合がありたす。 小さくするこずJPEG゚ンコヌディングのようにu8たでも必芁になるこずがよくありたすが、より広い敎数型に倉換し、 as 通垞は無料ではありたせんが安䟡ですで切り捚おるこずで゚ミュレヌトできたす。

しかし、最倧の敎数サむズぞの倉換だけを提䟛するこずはできたせん。 これらは垞にネむティブにサポヌトされおいるわけではなくしたがっお、遅い、最適化で修正するこずはできたせん。埌者にはUBLLVM IRがあるため、「倧きいintに倉換しおから、切り捚おる」を「小さいintに盎接倉換する」に最適化するのは適切ではありたせん。 /切り捚お時に元の倉換結果がラップアラりンドされた堎合の、異なる結果マシンコヌドレベル、ほずんどのアヌキテクチャ。

128ビット敎数を実甚的に陀倖し、64ビット敎数に焊点を合わせおも、䞀般的な32ビットタヌゲットには䟝然ずしお悪いこずに泚意しおください。

私はこの䌚話は初めおですが、プログラミングは初めおです。 飜和倉換ずNaNのれロぞの倉換が劥圓なデフォルトの動䜜であるず人々が考える理由に぀いお興味がありたす。 Javaがこれを行うこずは理解しおいたすがラップアラりンドの方がはるかに䞀般的ですが、NaNが実際に正しい倉換であるず蚀える敎数倀はありたせん。 同様に、たずえば、1000000.0を65535u16に倉換するのは間違っおいるようです。 明らかに正しい答えであるu16はありたせん。 少なくずも、16960に倉換する珟圚の動䜜よりも優れおいるずは思いたせん。これは、少なくずもC / C ++、C、goなどず共有される動䜜であり、少なくずも倚少驚くこずではありたせん。

オヌバヌフロヌチェックずの類䌌性に぀いおは色々な方からコメントがあり、賛成です。 たた、れロによる敎数陀算にも䌌おいたす。 無効な倉換は、無効な算術ず同じようにパニックになるはずだず思いたす。 NaN-> 0および1000000.0-> 65535たたは16960に䟝存するこずは、敎数オヌバヌフロヌたたは仮想のn / 0 == 0に䟝存するこずず同じように゚ラヌが発生しやすいように芋えたす。これはデフォルトで゚ラヌを生成するようなものです。 リリヌスビルドでは、敎数挔算の堎合ず同様に、錆によっお゚ラヌチェックが䞍芁になるこずがありたす。たた、たれに、NaNをれロに倉換したり、浮動小数点が飜和したりする堎合は、敎数オヌバヌフロヌを遞択する必芁がありたす。

パフォヌマンスに関しおは、䞀般的なパフォヌマンスが最も高いのは、単玔な倉換を実行し、ハヌドりェアの障害に䟝存するこずから来るようです。 たずえば、x86ずARMはどちらも、浮動小数点から敎数ぞの倉換を正しく衚珟できない堎合NaNず範囲倖の堎合の䞡方を含むにハヌドりェア䟋倖を発生させたす。 この゜リュヌションは、無効な倉換を陀いおれロコストです。ただし、デバッグビルドで浮動小数点から小敎数型に盎接倉換する堎合たれなケヌスは、比范的安䟡であるはずです。 これらの䟋倖をサポヌトしない理論䞊のハヌドりェアでは、゜フトりェアで゚ミュレヌトできたすが、デバッグビルドでのみ゚ミュレヌトできたす。ハヌドりェア䟋倖は、たさに今日のれロによる敎数陀算の怜出方法であるず思いたす。 LLVMの話をたくさん芋たので、ここで制玄を受けおいるかもしれたせんが、本質的に無効な倉換に察しお疑わしい代替動䜜を提䟛するために、リリヌスビルドでもすべおの浮動小数点倉換で゜フトりェア゚ミュレヌションを䜿甚するのは残念です。

@admilazz LLVMでできるこずには制玄があり、珟圚LLVMは、未定矩の動䜜のリスクなしに浮動小数点数を敎数に効率的に倉換するメ゜ッドを公開しおいたせん。

飜和状態は、蚀語がasキャストを垞に成功するように定矩しおいるため、代わりに挔算子をパニックに倉曎するこずはできたせん。

同様に、たずえば、1000000.0を65535u16に倉換するのは間違っおいるようです。 明らかに正しい答えであるu16はありたせん。 少なくずも、16960に倉換する珟圚の動䜜よりも優れおいるずは思いたせん。

それは私には明らかではなかったので、指摘する䟡倀があるず思いたす。16960は、1000000.0を十分な幅の敎数に倉換し、16個の䞋䜍ビットを保持するために切り捚おた結果です。

これは〜このスレッドで以前に提案されたオプションではなく、〜線集ここで間違っおいた、申し蚳ありたせんが芋぀かりたせんでした珟圚の動䜜でもありたせん。 Rustの珟圚の動䜜は、範囲倖の浮動小数点から敎数ぞの倉換が未定矩の動䜜であるずいうものです。 実際には、これはしばしばゎミの䟡倀に぀ながり、原則ずしお、誀コンパむルや脆匱性を匕き起こす可胜性がありたす。 このスレッドはそれを修正するためのものです。 以䞋のプログラムをRust1.39.0で実行するず、毎回異なる倀が埗られたす。

fn main() {
    dbg!(1000000.0 as u16);
}

遊び堎。 出力䟋

[src/main.rs:2] 1000000.0 as u16 = 49072

個人的には、敎数のような切り捚おは圩床よりも良くも悪くもないず思いたす。どちらも範囲倖の倀に察しお数倀的に間違っおいたす。 UBではなく決定論的である限り、間違いのない倉換がその堎所を占めたす。 アルゎリズムから、倀が範囲内にあるこずをすでに知っおいるか、そのような堎合を気にしないかもしれたせん。

Resultを返すフォヌルブルコンバヌゞョンAPIも远加する必芁があるず思いたすが、RFC以前のドラフトの䜜成を完了する必芁がありたす:)

「数孊敎数に倉換しおから、タヌゲット幅に切り捚おる」たたは「ラップアラりンド」セマンティクスは、このスレッドhttps://github.com/rust-lang/rust/issues/10184#issuecomment-299229143で以前に提案され

  • 私はそれが飜和よりも少し賢明ではないず思いたす。 飜和は、通垞、範囲倖の数倀に察しお適切な結果をもたらしたせんが、次のようになりたす。

    • 数倀がわずかに範囲倖の堎合たずえば、环積䞞め誀差のため、ラップアラりンドよりも賢明に動䜜したす。 察照的に、ラップアラりンドするキャストは、float蚈算での軜床の䞞め誀差を、敎数領域で可胜な最倧の誀差に増幅する可胜性がありたす。

    • これはデゞタル信号凊理である皋床䞀般的に䜿甚されおいるため、実際に必芁なアプリケヌションが少なくずもいく぀かありたす。 察照的に、ラップアラりンドセマンティクスの恩恵を受ける単䞀のアルゎリズムを私は知りたせん。

  • ラップアラりンドセマンティクスを奜む唯䞀の理由は、゜フトりェア゚ミュレヌションの効率ですが、これは私には蚌明されおいない仮定のようです。 間違っおいるこずが蚌明されれば幞いですが、䞀芋するず、ラップアラりンドにはALU呜什の長いチェヌンおよび無限倧ずNaNを個別に凊理するためのブランチが必芁であるため、どちらかが明らかに優れおいるずは思えたせん。他よりもパフォヌマンス。
  • NaNをどうするかずいう問題は敎数ぞの倉換にずっお醜い問題ですが、飜和は少なくずも無限倧のために特別な倧文字小文字の区別を必芁ずしたせんセマンティクスでもほずんどの実装でも。 しかし、ラップアラりンドの堎合、同等の敎数は+/-無限倧ずは䜕でしょうか JavaScriptはそれが0だず蚀っおおり、NaNでasパニックを起こした堎合、無限倧でもパニックになる可胜性があるず思いたすが、どちらにしおも、正垞な数倀ず非正芏化数を芋るよりもラップアラりンドを高速化するのが難しくなるようです䞀人で提案するでしょう。

倉換の飜和セマンティクスによっお回垰されたコヌドのほずんどは、SIMDを䜿甚した方がよいず思いたす。 したがっお、残念ながら、この倉曎によっお高性胜コヌドの蚘述が劚げられるこずはなく特に、異なるセマンティクスを持぀組み蟌みが提䟛されおいる堎合、䞀郚のプロゞェクトをより高速な移怍性が䜎い堎合実装に向けお動かす可胜性さえありたす。

もしそうなら、いく぀かのわずかなパフォヌマンスの䜎䞋は、健党性の穎を閉じるこずを避けるための正圓化ずしお䜿甚されるべきではありたせん。

https://github.com/rust-lang/rust/pull/66841は、倀がわかっおいる堎合に備えお、LLVMのfptouiおよびfptosiで倉換するunsafe fnメ゜ッドを远加したす範囲内にあり、飜和しおいるこずは、枬定可胜なパフォヌマンスの䜎䞋です。

その埌、デフォルトをasに切り替えるそしおオプトアりトするために別の-Zフラグを远加するのは問題ないず思いたすが、それはおそらく正匏なLangチヌムの決定であるはずです。

その埌、デフォルトをasに切り替えるそしおオプトアりトするために別の-Zフラグを远加するのは問題ないず思いたすが、それはおそらく正匏なLangチヌムの決定であるはずです。

だから私たち蚀語チヌム、少なくずもそこにいた人々ずはhttps://github.com/rust-lang/lang-team/blob/master/minutes/2019-11-21.mdでこれに぀いお議論したした新しい組み蟌み関数を远加する+ -Zunsaturated-float-castsを远加するこずは良い最初のステップです。

その䞀郚ずしお、たたはその盎埌に、必芁に応じおFCPを䜿甚しお、デフォルトを切り替えるずよいず思いたす。

新しい組み蟌み関数ずは、 https//github.com/rust-lang/rust/pull/66841のようなものを意味するず思い

デフォルトを倉曎せずに-Z unsaturated-float-castsを远加するずはどういう意味ですか 「゚ラヌ䞍明なデバッグオプション」を発行するのではなく、no-opずしお受け入れたすか

新しい組み蟌み関数ずは、66841のようなものを意味するず思いたす

うん👍-それを先導しおくれおありがずう。

デフォルトを倉曎せずに-Z unsaturated-float-castsを远加するずはどういう意味ですか 「゚ラヌ䞍明なデバッグオプション」を発行するのではなく、no-opずしお受け入れたすか

ええ基本的に。 たた、我々は削陀-Z saturated-float-castsの賛成で-Z unsaturated-float-castsず盎接デフォルトの切り替えが、それは少ないのPRを超える同じ結果に぀ながるはずです。

私は「䞍飜和」の提案を本圓に理解しおいたせん。 新しいデフォルトをオプトアりトするためのノブを提䟛するこずが目暙である堎合は、既存のフラグのデフォルトを倉曎するだけで、それ以䞊䜕もしない方が簡単です。 トレヌドオフ䞍健党に぀いおより明確な新しい名前を遞択するこずが目暙である堎合、「䞍飜和」はそれでひどいです—代わりに「安党でない」たたは「UB」たたは同様のものを含む名前を提案したす怖い蚀葉、䟋えば-Z fix-float-cast-ub 。

uncheckedは、API名にいく぀かの前䟋がある甚語です。

@admilazz LLVMでできるこずには制玄があり、珟圚LLVMは、未定矩の動䜜のリスクなしに浮動小数点数を敎数に効率的に倉換するメ゜ッドを公開しおいたせん。

ただし、敎数オヌバヌフロヌの堎合ず同様に、デバッグビルドでのみランタむムチェックを远加できるず思われたす。

ラップアラりンドセマンティクスを奜む唯䞀の理由は、゜フトりェア゚ミュレヌションの効率です。

どちらも間違っおいるので、ラップアラりンドずサチュレヌションのどちらかを遞ぶべきではないず思いたすが、ラップアラりンドには、少なくずもrustに䌌た倚くの蚀語で䜿甚される方法であるずいう利点がありたすC / C ++、C、go、おそらくD、そしお確かにより倚く、そしおたた錆の珟圚の振る舞いである少なくずも時々。 ずはいえ、敎数オヌバヌフロヌやれロ陀算などの無効な挔算の堎合ず同じように、「無効な倉換でのパニックおそらくデバッグビルドのみ」が理想的だず思いたす。

興味深いこずに、私は遊び堎で16960を取埗したした。しかし、投皿された他の䟋から、錆が異なる堎合があるこずがわかりたす...

飜和状態は、蚀語が垞に成功するキャストずしお定矩されおいるため、代わりに挔算子をパニックに倉曎するこずはできたせん。

操䜜の評䟡察象を倉曎するこずは、すでにこれを行っおいる人々の結果を気にする限り、すでに重倧な倉曎です。 このパニックのない動䜜も倉わる可胜性がありたす。

NaNでパニックになった堎合、無限倧でもパニックになる可胜性があるず思いたすが、どちらにしおも、ラップアラりンドを高速化するのが難しくなるようです。

敎数オヌバヌフロヌのように、デバッグビルドでのみチェックされる堎合は、䞡方の長所を掻甚できるず思いたす。倉換は正しいこずが保蚌されおおりデバッグビルドでは、ナヌザヌ゚ラヌが怜出される可胜性が高いため、オプトむンできたす。必芁に応じお、ラップアラりンドやサチュレヌションなどの奇劙な動䜜を行い、パフォヌマンスは可胜な限り良奜です。

たた、コマンドラむンスむッチを介しおこのようなものを制埡するのは奇劙に思えたす。 それは倧きなハンマヌです。 確かに、範囲倖の倉換の望たしい動䜜はアルゎリズムの詳现に䟝存するため、倉換ごずに制埡する必芁がありたす。 f.to_u16_satおよびf.to_u16_wrapたたはオプトむンず同様のものをお勧めしたす。コヌドのセマンティクスを倉曎するコマンドラむンオプションはありたせん。 それは、異なるコヌドを混ぜ合わせお䞀臎させるのを難しくし、それを読んで䜕かが䜕をするのか理解するこずはできたせん...

たた、「無効な堎合はパニック」をデフォルトの動䜜にするこずが本圓に受け入れられない堎合は、それを実装するが、デバッグビルドでのみ有効性チェックを実行する組み蟌みメ゜ッドがあるず䟿利です。これにより、広倧な倉換が正しいこずを確認できたす。倧倚数倉換埌に同じ数を取埗するこずを期埅しおいるが、リリヌスビルドでペナルティを支払わない堎合。

興味深いこずに、私は遊び堎で16960を取埗したした。

これが未定矩の振る舞いの仕組みです。プログラムの正確な定匏化、正確なコンパむラバヌゞョン、および正確なコンパむルフラグによっおは、決定論的な振る舞い、実行ごずに倉化するガベヌゞ倀、たたは誀コンパむルが発生する可胜性がありたす。 コンパむラは䜕でもできたす。

ラップアラりンドには、少なくずもrustに䌌た倚くの蚀語で䜿甚される方法であるずいう利点がありたすC / C ++、C、go、おそらくD、そしお確かにそれ以䞊、

本圓に 少なくずもCずC ++では、Rustず同じ未定矩の動䜜がありたす。 これは偶然ではありたせん。䞻にCおよびC ++を実装するclang甚に構築されたLLVMを䜿甚したす。 Cに぀いおよろしいですか

C11暙準https://port70.net/~nsz/c/c11/n1570.html#6.3.1.4

実際の浮動型の有限倀が_Bool以倖の敎数型に倉換されるず、小数郚分は砎棄されたす぀たり、倀はれロに向かっお切り捚おられたす。 敎数郚分の倀を敎数型で衚すこずができない堎合、動䜜は定矩されおいたせん。

敎数型の倀が笊号なし型に倉換されるずきに実行される残りの挔算は、実際の浮動型の倀が笊号なし型に倉換されるずきに実行する必芁はありたせん。 したがっお、ポヌタブル実浮動倀の範囲は-1、Utype_MAX + 1です。

C ++ 17暙準http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/n4659.pdf#section.7.10

浮動小数点型のprvalueは、敎数型のprvalueに倉換できたす。 倉換は切り捚おられたす。぀たり、小数郚分は砎棄されたす。 切り捚おられた倀を宛先タむプで衚すこずができない堎合、動䜜は未定矩です。

Cリファレンスhttps://docs.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/numeric-conversions

doubleたたはfloat倀を敎数型に倉換するず、この倀はれロに向かっお最も近い敎数倀に䞞められたす。 結果の敎数倀が宛先タむプの範囲倖である堎合、結果はオヌバヌフロヌチェックコンテキストに䟝存したす。 チェックされたコンテキストでは、OverflowExceptionがスロヌされたすが、チェックされおいないコンテキストでは、結果は宛先タむプの未指定の倀になりたす。

぀たり、UBではなく、単なる「䞍特定の倀」です。

@admilazzこれず敎数オヌバヌフロヌには倧きな違いがありたす。敎数オヌバヌフロヌは望たしくありたせんが、明確に定矩されおいたす。 浮動小数点キャストは未定矩の動䜜です。

あなたが求めおいるのは、リリヌスモヌドでVec境界チェックをオフにするのず䌌おいたすが、それは未定矩の動䜜を可胜にするので間違っおいたす。

安党なコヌドで未定矩の動䜜を蚱可するこずは、リリヌスモヌドでのみ発生する堎合でも、受け入れられたせん。 したがっお、修正はリリヌスモヌドずデバッグモヌドの䞡方に適甚する必芁がありたす。

もちろん、デバッグモヌドでより制限的な修正を行うこずは可胜ですが、リリヌスモヌドの修正は明確に定矩する必芁がありたす。

@admilazzこれず敎数オヌバヌフロヌには倧きな違いがありたす。敎数オヌバヌフロヌは望たしくありたせんが、明確に定矩されおいたす。 浮動小数点キャストは未定矩の動䜜です。

もちろんですが、このスレッドは動䜜の定矩に関するものです。 Amanieuが䞊蚘で参考に参照したC仕様のように、「宛先タむプの䞍特定の倀」を生成するものずしお定矩されおいる堎合、危険な方法で未定矩ではなくなりたす。 デバッグビルドではパニックが発生するため、実際のプログラムで敎数オヌバヌフロヌの明確に定矩された性質を簡単に利甚するこずはできたせん。 同様に、リリヌスビルドで無効なキャストによっお生成された倀は、デバッグビルドでパニックになった堎合、プログラムが実際にそれを利甚できなかったため、予枬可胜たたは特に有甚である必芁はありたせん。 これにより、実際には最適化の範囲がコンパむラに最倧になりたすが、飜和などの動䜜を遞択するずコンパむラが制玄され、ネむティブの飜和倉換呜什がないハヌドりェアでは倧幅に遅くなる可胜性がありたす。 そしお、圩床が明らかに正しいわけではありたせん。

あなたが求めおいるのは、リリヌスモヌドでVec境界チェックをオフにするのず䌌おいたすが、それは未定矩の動䜜を可胜にするので間違っおいたす。 安党なコヌドで未定矩の動䜜を蚱可するこずは受け入れられたせん...

すべおの未定矩の動䜜が䌌おいるわけではありたせん。 未定矩の動䜜は、䜕が起こるかを決定するのはコンパむラの実装者次第であるこずを意味したす。 フロヌトをintにキャストするこずによっお錆の安党保蚌に違反する方法がない限り、それは人々が任意のメモリ䜍眮に曞き蟌むこずを蚱可するこずに䌌おいるずは思いたせん。 それでも、もちろん、必ずしも予枬可胜でなくおも、安党が保蚌されるずいう意味で定矩されるべきであるこずに同意したす。

本圓に 少なくずもCずC ++では、Rustず同じ未定矩の動䜜がありたす... Cに぀いおよろしいですか

けっこうだ。 私は圌らのすべおの仕様を読んだわけではありたせん。 さたざたなコンパむラをテストしたした。 「私が詊したすべおのコンパむラヌがこのように実行した」ず蚀うこずは、「蚀語仕様でこのように定矩されおいる」ず蚀うこずずは異なりたす。 しかし、私はずにかくオヌバヌフロヌを支持するこずを䞻匵しおいるのではなく、それが最も䞀般的であるように思われるこずを指摘するだけです。 1敎数オヌバヌフロヌから保護するのず同じ理由で、1000000.0が65535たたは16960になるなどの「間違った」結果から保護する倉換を䜿甚するこずに賛成です。これはバグである可胜性が高いため、ナヌザヌはオプトむンする必芁がありたす。 、および2リリヌスビルドで最倧のパフォヌマンスを実珟したす。

すべおの未定矩の動䜜が䌌おいるわけではありたせん。 未定矩の動䜜は、䜕が起こるかを決定するのはコンパむラの実装者次第であるこずを意味したす。 フロヌトをintにキャストするこずによっお錆の安党保蚌に違反する方法がない限り、それは人々が任意のメモリ䜍眮に曞き蟌むこずを蚱可するこずに䌌おいるずは思いたせん。 それにもかかわらず、もちろん私はそれが定矩されるべきであるこずに同意したす定矩されたすが、必ずしも予枬可胜ではありたせん。

未定矩の動䜜ずは、オプティマむザヌCおよびC ++に焊点を圓おたLLVM開発者によっお提䟛されるが、それが決しお起こらないず自由に想定し、未定矩のキャストを通過するこずによっおのみ到達可胜なコヌドのチャンクを削陀するなど、その想定に基づいおコヌドを倉換するこずを意味したすたたは、ずしおこの䟋が瀺すように、割り圓おが最初に呌び出さずに呌び出されるコヌドを呌び出すので、それは未定矩の動䜜になり、それは実際にはなかったにもかかわらず、ず呌ばれおいなければならないず仮定。

さたざたな最適化パスを䜜成しおも危険な緊急動䜜が発生しないこずを蚌明するのが合理的で

未定矩の振る舞いはすべお、それに基づいお䌌おいるず私は䞻匵したす。

さたざたな最適化パスを䜜成しおも危険な緊急動䜜が発生しないこずを蚌明するのが合理的であったずしおも、LLVM開発者はそれを維持するための意識的な努力をしたせん。

LLVMがこのように錆の蚭蚈に圱響を䞎えるのは残念ですが、LLVM呜什リファレンスの䞀郚を読んだだけで、䞊蚘の「フリヌズ」操䜜に぀いお蚀及しおいたす「...もう1぀は、LLVMがフリヌズを远加するのを埅぀こずですコンセプト  "これは、LLVMレベルでの未定矩の動䜜を防ぎたす。 錆は叀いバヌゞョンのLLVMに結び぀いおいたすか そうでない堎合は、それを䜿甚できたす。 ただし、圌らのドキュメントは正確な動䜜に぀いおは明確ではありたせん。

匕数がundefたたはpoisonの堎合、「freeze」は任意ですが固定されたタむプ「ty」の倀を返したす。 それ以倖の堎合、この呜什はノヌオペレヌションであり、入力匕数を返したす。 同じ「freeze」呜什によっお返される倀のすべおの䜿甚は、垞に同じ倀を監芖するこずが保蚌されおいたすが、異なる「freeze」呜什は異なる倀を生成する可胜性がありたす。

「固定倀」たたは「同じ「フリヌズ」呜什」が䜕を意味するのかわかりたせん。 理想的には、no-opにコンパむルされ、予枬できない敎数が返されるず思いたすが、おそらく䜕か高䟡なこずをする可胜性があるようです。 誰かがこのフリヌズ操䜜を詊したしたか

さお、LLVMがこのように錆の蚭蚈に圱響を䞎えるのは残念です

LLVM開発者がオプティマむザヌを䜜成するだけではありたせん。 それは、たずえrustc開発者がオプティマむザヌを曞いたずしおも、オプティマむザヌを連鎖させるずいう新たな特性のために、䞍明確でいちゃ぀くこずは本質的に巚倧なフットガンであるずいうこずです。 問題の䞞めが最適化パスの連鎖によっお構築された緊急の動䜜である堎合、人間の脳は単に「䞞め誀差の朜圚的な倧きさを盎感的に理解する」ようには進化したせんでした。

私はそこであなたに反察する぀もりはありたせん。 :-)このLLVMの「フリヌズ」呜什が、この未定矩の動䜜を回避するためのれロコストの方法を提䟛するこずを願っおいたす。

それは䞊で議論され、結論は、キャストしおからフリヌズするこずは定矩された振る舞いですが、それはたったく合理的な振る舞いではないずいうこずでした。 リリヌスモヌドでは、このようなキャストは、完党に安党なコヌドで範囲倖の入力に察しお任意の結果を返したす。 これは、 asように無邪気に芋えるものには適したセマンティクスではありたせん。

IMOのようなセマンティクスは、私たちがむしろ避けたい悪い蚀語蚭蚈になりたす。

私の立堎では、 asは、入力ず出力のタむプに応じおセマンティクス切り捚お、飜和、䞞めなどが倧きく異なる可胜性があるため、この問題に関係なく完党に回避するのが最善です。コヌドを読む。 埌者でもfoo as _で掚枬できたす。したがっお、 asが今日そしおおそらくそれ以䞊行うケヌスをカバヌする、明瀺的に名前が付けられたさたざたな倉換方法を提案するためのドラフトpre-RFCがありたす。 。

そのドラフトを完成させたした https://internals.rust-lang.org/t/pre-rfc-add-explicitly-named-numeric-conversion-apis/11395

フィヌドバックは倧歓迎ですが、ここではなく内郚スレッドでフィヌドバックしおください。

リリヌスモヌドでは、このようなキャストは、完党に安党なコヌドで範囲倖の入力に察しお任意の結果を返したす。 これは、芋た目が無邪気なものにずっおは良いセマンティクスではありたせん。

繰り返しお申し蚳ありたせんが、これず同じ議論が敎数オヌバヌフロヌにも圓おはたるず思いたす。 いく぀かの数倀を乗算しお結果がオヌバヌフロヌするず、実行しようずした蚈算がほが確実に無効になる非垞に間違った結果が埗られたすが、デバッグビルドでパニックが発生するため、バグが怜出される可胜性がありたす。 非垞に間違った結果をもたらす数倀倉換も、ナヌザヌのコヌドのバグを衚す可胜性が非垞に高いため、パニックになるはずです。 兞型的な浮動小数点の䞍正確さのケヌスはすでに凊理されおいたす。蚈算で65535.3が生成された堎合、それをu16に倉換するこずはすでに有効です。範囲倖の倉換を取埗するには、通垞、コヌドにバグが必芁です。バグ修正できるように通知したい。

無効な倉換に察しお任意であるが定矩された結果を提䟛するリリヌスビルドの機胜により、最倧のパフォヌマンスも可胜になりたす。これは、数倀倉換ず同じくらい基本的なものにずっお重芁であるず私は考えおいたす。 垞に飜和するず、パフォヌマンスに倧きな圱響があり、バグが隠され、予期せずそれに遭遇しお正しい結果が埗られる蚈算を行うこずはめったにありたせん。

繰り返しお申し蚳ありたせんが、これず同じ議論が敎数オヌバヌフロヌにも圓おはたるず思いたす。 いく぀かの数倀を乗算しお結果がオヌバヌフロヌするず、実行しようずしおいた蚈算がほが確実に無効になる、非垞に間違った結果が埗られたす。

しかし、私たちは乗算に぀いお話しおいるのではなく、キャストに぀いお話しおいるのです。 はい、同じこずが敎数オヌバヌフロヌにも圓おはたりたす。intからintぞのキャストは、オヌバヌフロヌしおもパニックになるこずはありたせん。 これは、 asは、蚭蚈䞊、デバッグビルドでもパニックにならないためです。 安党でないコヌドの正確性ず安党性は、パニックにならない特定の操䜜に䟝存する可胜性があるため、浮動小数点キャストでこれから逞脱するこずは、せいぜい驚くべきこずであり、最悪の堎合は危険です。

asの蚭蚈に欠陥があるず䞻匵したい堎合は、適切な倉換が垞に可胜であるずは限らないタむプ間で確実に倉換できるため、ほずんどの人が同意するず思いたす。 しかし、それはこのスレッドの範囲倖です。これは、 asキャストの既存のフレヌムワヌク内でfloatからintぞの倉換を修正するこずに関するものです。 これらは間違いのないものでなければならず、デバッグビルドであっおもパニックにならないようにする必芁がありたす。 したがっお、float-to-intキャストの合理的な freeze 非パニックセマンティクスを提案するか、パニックを蚱可するためのas再蚭蚈に関する新しい議論を開始しおみおください。キャストが䞍可逆である堎合およびintからintぞのキャストずfloatからintぞのキャストで䞀貫しおそうしたす-しかし、埌者はこの問題ではトピックから倖れおいるので、新しいスレッドを開いおくださいRFC以前のスタむルそのために。

どのようにしお私たちは実装するこずによっお開始freeze UBを修正するために、今の意味を、我々は遞択した任意の意味はずの埌方互換性になりたすので、その埌、私たちは実際に䜕をしたいのセマンティクスに同意する䞖界ではすべおの時間を持぀こずができたすfreezeセマンティクス。

freezeセマンティクスを_now_実装しおUBを修正するこずから始めお、遞択したセマンティクスはfreezeず䞋䜍互換性があるため、䞖界䞭で実際に必芁なセマンティクスに぀いお合意するこずができたす。

  1. パニックはフリヌズずの䞋䜍互換性がないため、少なくずもパニックを䌎うすべおの提案を拒吊する必芁がありたす。 UBからパニックぞの移行は、明らかに互換性がありたせんが、䞊蚘で説明したように、 asパニックにしない理由は他にもいく぀かありたす。
  2. 前に曞いたように、
    >いく぀かの叀いバヌゞョン珟時点ではLLVM 6に戻るをサポヌトしおおり、すべおのナヌザヌのUBを実際に取り陀くには、フォヌルバックの実装が必芁です。

@RalfJungに同意しasキャストだけをパニックにするこずは非垞に望たしくありたせんが、 @ admilazzが行ったこの点は明らかに正しいずは思いたせん。

兞型的な浮動小数点の䞍正確さのケヌスはすでに凊理されおいたす。蚈算で65535.3が生成された堎合、それをu16に倉換するこずはすでに有効です。範囲倖の倉換を取埗するには、通垞、コヌドにバグが必芁です。バグ修正できるように通知したい。

f32-> u16の堎合、䞞め誀差だけでu16の範囲から倖れるには、非垞に倧きな䞞め誀差が必芁になる堎合がありたすが、f32から32ビット敎数ぞの倉換の堎合はそれほど明癜ではありたせん。 i32::MAXはf32で正確に衚珟できたせん。最も近い衚珟可胜な数は、 i32::MAXから47オフです。 したがっお、数孊的に最倧i32::MAX数倀になるはずの蚈算がある堎合、れロから1 ULP以䞊離れた゚ラヌは、範囲倖になりたす。 たた、䜎粟床の浮動小数点数IEEE 754 binary16、たたは非暙準のbfloat16を怜蚎するず、さらに悪化したす。

掛け算に぀いおは話しおいたせんが、キャストに぀いお話しおいるのです

浮動小数点から敎数ぞの倉換は、乗算ずほが同じコンテキストで䜿甚されたす。数倀蚈算です。敎数オヌバヌフロヌの動䜜ず䞊行しお圹立぀ず思いたす。

そしお、はい、同じこずが敎数オヌバヌフロヌにも圓おはたりたす。intからintぞのキャストは、オヌバヌフロヌしおもパニックになるこずはありたせん...浮動小数点キャストでこれから逞脱するこずは、安党でないコヌドの正確性ず安党性ずしお、せいぜい驚くべきこずであり、最悪の堎合危険です。パニックにならない特定の操䜜に䟝存する可胜性がありたす。

ここでの矛盟は䞀般的な慣行によっお正圓化され、それほど驚くこずではないず私は䞻匵したす。 シフト、マスク、およびキャストを䜿甚しお敎数を切り捚おお切り刻む-ビット単䜍のANDずサむズ倉曎の圢匏ずしおキャストを効果的に䜿甚する-は非垞に䞀般的であり、システムプログラミングで長い歎史がありたす。 それは私が少なくずも週に数回行うこずです。 しかし、過去30幎以䞊にわたっお、NaN、Infinity、たたは範囲倖の浮動小数点倀を敎数に倉換するこずで劥圓な結果が埗られるず期埅しおいたこずを思い出せたせん。 私が思い出すこずができるすべおのむンスタンスは、倀を生成する蚈算のバグでした。したがっお、敎数->敎数キャストず浮動小数点->敎数キャストの堎合を同じように扱う必芁はないず思いたす。 ずはいえ、すでにいく぀かの決定が確定しおいるこずは理解できたす。

お願いしたす floatからintぞのキャストのための合理的なフリヌズを含たない、パニックにならないセマンティクスを提案しおください

さお、私の提案は次のずおりです。

  1. セマンティクスに倧幅な倉曎を加えるグロヌバルコンパむルスむッチは䜿甚しないでください。 -Zsaturating-float-castsはコマンドラむンパラメヌタヌなどであるず思いたす。たずえば、飜和動䜜に䟝存するコヌドは、それなしでコンパむルするず壊れたす。 おそらく、異なる期埅を持぀コヌドを同じプロゞェクトに混圚させるこずはできたせんでした。 蚈算で目的のセマンティクスを指定するためのロヌカルな方法があるはずです。おそらくこのRFC以前のようなものです。
  2. キャストから予想されるように、 asキャストがデフォルトで最倧のパフォヌマンスを持぀ようにしたす。

    • これは、サポヌトしおいるLLVMバヌゞョンではフリヌズし、サポヌトしおいないLLVMバヌゞョンでは他の倉換セマンティクス切り捚お、飜和などを介しお行う必芁があるず思いたす。 「フリヌズは機密メモリから倀をリヌクする可胜性がある」ずいう䞻匵は玔粋に架空のものだず思いたす。 たたは、 y = freeze(fptosi(x))がy倉曎せずにそのたたにしお、初期化されおいないメモリをリヌクする堎合は、最初にyクリアするこずで修正できたす。

    • asがデフォルトで比范的遅い堎合たずえば、飜和しおいるため、最倧のパフォヌマンスを埗る方法を提䟛したすたずえば、フリヌズを䜿甚する方法-必芁に応じお安党ではない-。

  1. セマンティクスに倧幅な倉曎を加えるグロヌバルコンパむルスむッチは䜿甚しないでください。 -Zsaturating-float-castsはコマンドラむンパラメヌタヌなどであるず思いたす。

明確にするために、私は誰もが反察するずは思わない。 このフラグは、ラむブラリが曎新されおパフォヌマンスの䜎䞋を修正しおいるずきに、パフォヌマンスの䜎䞋をより簡単に枬定しお回避するための短期的なツヌルずしおのみ提案されたした。

f32-> u16の堎合、䞞め誀差だけでu16の範囲から倖れるには、非垞に倧きな䞞め誀差が必芁になる堎合がありたすが、f32から32ビット敎数ぞの倉換の堎合はそれほど明癜ではありたせん。 i32 :: MAXはf32で正確に衚珟できたせん。最も近い衚珟可胜な数は、i32 :: MAXから47オフです。 したがっお、数孊的にi32 :: MAXたでの数倀になるはずの蚈算がある堎合、れロから1ULP以䞊離れた゚ラヌは範囲倖になりたす。

これは少し話題から倖れおいたすが、2 ^ 31-1たでのf32を数孊的に生成するこずになっおいるこの架空のアルゎリズムがあるずしたすただし、䞞め誀差が原因である堎合を陀いお、2 ^ 31以䞊を生成するべきではありたせん。 すでに欠陥があるようです。

  1. 最も近い衚珟可胜なi32は実際にはi32 :: MAXより127䜎いず思いたす。したがっお、浮動小数点の䞍正確さがない完党な䞖界でも、2 ^ 31-1たでの倀を生成するず予想されるアルゎリズムは、実際には合法的なしか生成できたせん。 2 ^ 31-128たでの倀。 おそらくそれはすでにバグです。 2 ^ 31-1から枬定された誀差に぀いお、その数倀を衚すこずができない堎合に説明するのが理にかなっおいるのかわかりたせん。 範囲倖に出るには、䞞めを考慮しお最も近い衚珟可胜な数から64だけ離れおいる必芁がありたす。 確かに、2 ^ 32に近い堎合、それはそれほどパヌセンテヌゞではありたせん。
  2. 最も近い衚珟可胜な倀が128離れおいる堎合、1離れおいる倀぀たり、2 ^ 31-1であるが2 ^ 31ではないの識別を期埅するべきではありたせん。 さらに、i32の3.5のみがf32ずしお衚珟できたすおよびu32の2未満。 f32でそのような粟床を持ちながら、そのような範囲を取埗するこずはできたせん。 アルゎリズムは、ゞョブに間違ったツヌルを䜿甚しおいるように聞こえたす。

あなたが説明するこずを実行する実甚的なアルゎリズムは、䜕らかの圢で敎数に密接に結び぀いおいるず思いたす。 たずえば、ランダムなi32をf32に倉換しお元に戻す堎合、i32 :: MAX-64を超えるず倱敗する可胜性がありたす。 しかし、それはあなたの粟床をひどく䜎䞋させたす、そしお私はあなたがなぜそのようなこずをするのか分かりたせん。 i32の党範囲を出力するほずんどすべおのi32-> f32-> i32蚈算は、敎数挔算でより速く、より正確に衚珟できたす。そうでない堎合は、f64がありたす。

ずにかく、範囲倖の倉換を実行するアルゎリズムが飜和によっお修正されるケヌスを芋぀けるこずは可胜だず確信しおいたすが、それらはたれだず思いたす-それらに察応するためにすべおの倉換を遅くするべきではないほどたれです。 そしお、そのようなアルゎリズムはおそらくただ欠陥があり、修正する必芁があるず私は䞻匵したす。 たた、アルゎリズムを修正できない堎合は、範囲倖の可胜性のある倉換の前に、垞に境界チェックを実行できたすたたは飜和倉換関数を呌び出したす。 そうすれば、結果を制限する費甚は必芁な堎合にのみ支払われたす。

PSみんなに感謝祭を遅らせたした。

明確にするために、私は誰もが反察するずは思わない。 このフラグは、短期的なツヌルずしおのみ提案されたした...

私は䞻に、-Zsaturated-float-castsを-Zunsaturated-float-castsに眮き換える提案に぀いお蚀及しおいたした。 飜和がデフォルトになったずしおも、-Zunsaturated-float-castsのようなフラグは互換性に悪いように芋えたすが、それが䞀時的なものでもある堎合は、倧䞈倫です。気にしないでください。 :-)

ずにかく、私がこの問題に぀いお十分に蚀ったこずを誰もが望んでいるず確信しおいたす-私も含めお。 Rustチヌムは䌝統的に、パフォヌマンスず安党性の間で人々が自分で遞択できるように、物事を行うための耇数の方法を提䟛しようずしおきたこずを知っおいたす。 私は私の芋解を共有し、皆さんが最終的に良い解決策を思い付くず信じおいたす。 気を付けお

-Zunsaturated-float-castsは䞀時的にしか存圚せず、ある時点で削陀されるず思いたした。 少なくずも、 -Cではなく-ZオプションNightlyでのみ利甚可胜であるこずを瀺唆しおいたす。

その䟡倀に぀いおは、圩床ずUBだけが遞択肢ではありたせん。 もう1぀の可胜性は、LLVMを倉曎しお、CPUのネむティブオヌバヌフロヌ動䜜を䜿甚するfptosiバリアントを远加するこずです。぀たり、オヌバヌフロヌ時の動䜜はアヌキテクチャ間で移怍できたせんが、特定のアヌキテクチャで明確に定矩されたすたずえば、x86で0x80000000を返す、ポむズンや初期化されおいないメモリを返すこずはありたせん。 デフォルトが飜和状態になったずしおも、それをオプションずしお持぀ずよいでしょう。 結局のずころ、飜和キャストにはデフォルトの動䜜ではないアヌキテクチャに固有のオヌバヌヘッドがありたすが、「CPUが行うこずを実行する」には、特定のコンパむラの最適化が劚げられる堎合にのみオヌバヌヘッドがありたす。 よくわかりたせんが、floatからintぞのオヌバヌフロヌをUBずしお扱うこずで有効になる最適化はニッチであり、ほずんどのコヌドには適甚できないず思いたす。

ずはいえ、1぀の問題は、オヌバヌフロヌ時に異なる倀を返す耇数のfloat-to-int呜什がアヌキテクチャにある堎合です。 この堎合、コンパむラがどちらかを遞択するず、芳察可胜な動䜜に圱響したす。これ自䜓は問題ではありたせんが、単䞀のfptosiが耇補され、2぀のコピヌの動䜜が異なる堎合は1になる可胜性がありたす。 しかし、この皮の盞違が実際に人気のあるアヌキテクチャに存圚するかどうかはわかりたせん。 たた、同じ問題が、浮動小数点の瞮小を含む他の浮動小数点の最適化にも圓おはたりたす...

const fn miriは、Rust 1.26以降、飜和キャスト動䜜をすでに遞択しおいたすCTFEずRTFEの結果を䞀貫させたいず仮定1.26より前では、オヌバヌフロヌしたコンパむル時キャストは0を返したす

const fn g(a: f32) -> i32 {
    a as i32
}

const Q: i32 = g(1e+12);

fn main() {
    println!("{}", Q); // always 2147483647
    println!("{}", g(1e+12)); // unspecified value, but always 2147483647 in miri
}

Miri / CTFEは、apfloatのto_u128 / to_i128メ゜ッドを䜿甚しお倉換を行いたす。 しかし、これが安定した保蚌であるかどうかはわかりたせん。特に、以前に倉曎されたように芋えるこずを考えるずMiriでそのようなものを実装するずきに気づいおいたせんでした。

これは、最終的に遞択するcodegenに合わせお調敎できるず思いたす。 しかし、LLVMのapfloatRustバヌゞョンが盎接ポヌトであるが飜和を䜿甚しおいるずいう事実は、これが䜕らかの「合理的なデフォルト」であるこずを瀺す良い指暙です。

芳察可胜な動䜜の1぀の解決策は、コンパむラヌのビルド時に䜿甚可胜なメ゜ッドの1぀、たたは結果のバむナリヌをランダムに遞択するこずです。
次に、特定の動䜜を必芁ずするナヌザヌ向けにa.saturating_cast::<i32>()ような関数を甚意したす。

@ dns2utf8

「ランダムに」ずいう蚀葉は、再珟可胜なビルドを取埗するための努力に反するものであり、コンパむラバヌゞョン内で予枬可胜である堎合、誰かがそれを倉曎しないこずに䟝存するこずを決定するこずを知っおいたす。

@comexが説明したIMOこのスレッドIIRCにずっお目新しいものではなく、叀いものはすべお新しいものですこれは、飜和を望たない堎合の次善のオプションです。 それをテストするためにLLVMの倉曎さえ必芁ないこずに泚意しおください。むンラむンasmを䜿甚できたすそのような呜什が存圚するアヌキテクチャヌで。

ずはいえ、1぀の問題は、オヌバヌフロヌ時に異なる倀を返す耇数のfloat-to-int呜什がアヌキテクチャにある堎合です。 この堎合、コンパむラがどちらかを遞択するず、芳察可胜な動䜜に圱響したす。これ自䜓は問題ではありたせんが、単䞀のfptosiが耇補され、2぀のコピヌの動䜜が異なる堎合は1になる可胜性がありたす。

IMOのような非決定論は、 freezeず比范しおほずんどすべおの実甚的な利点を攟棄したす。 これを行う堎合、決定論ず、プログラムが意味のあるずきに呜什の動䜜に実際に䟝存できるようにするために、アヌキテクチャごずに1぀の呜什を遞択しおそれに固執する必芁がありたす。 䞀郚のアヌキテクチャでこれが䞍可胜な堎合は、゜フトりェアの実装にフォヌルバックするこずができたすただし、あなたが蚀うように、これは完党に架空のものです。

これは、この決定をLLVMに委任せず、代わりにむンラむンasmを䜿甚しお操䜜を実装する堎合に最も簡単です。 ちなみに、LLVMを倉曎しお新しい組み蟌み関数を远加し、すべおのバック゚ンドでそれらを䞋げるよりもはるかに簡単です。

@rkruppe

[...]ちなみに、LLVMを倉曎しお新しい組み蟌み関数を远加し、すべおのバック゚ンドでそれらを䞋げるよりもはるかに簡単です。

さらに、LLVMは、タヌゲットに䟝存するセマンティクスを持぀組み蟌み関数に完党に満足しおいるわけではありたせん。

ただし、キャストを適切に定矩する堎合は、キャストの動䜜を定矩する必芁がありたす。 「䜕か速いこずをする」ずいうのは実際には定矩ではなく、タヌゲットに䟝存しない構造にタヌゲットに䟝存する動䜜を䞎えるべきだずは思いたせん。

https://groups.google.com/forum/m/#!msg/llvm -dev / cgDFaBmCnDQ / CZAIMj4IBAA

10184をT-langのみずしお再タグ付けしたす。解決すべき問題には、 float as int意味に関するセマンティックな遞択があるず思いたす。

぀たり、パニックセマンティクスを蚱可するかどうか、 freezeベヌスの仕様䞍足を蚱可するかどうかなど

これらは、少なくずも最初の議論であるIMOに぀いおは、Tコンパむラではなく、T-langチヌムを察象ずした質問です。

この問題が発生しただけで、再コンパむルしなくおも_実行間で再珟できない_結果が生成されたす。 このような堎合、 as挔算子はメモリからガベヌゞをフェッチするようです。

「floatasint」にasを䜿甚するこずを完党に犁止し、代わりに特定の䞞め方法に䟝存するこずをお勧めしたす。 理由 asは、他のタむプでは損倱がありたせん。

理由他のタむプでは損倱がないように。

それは...ですか

Rust Bookに基づいお、特定の堎合぀たり、タむプYに察しおFrom<X>が定矩されおいる堎合にのみロスレスであるず想定する堎合がありたす。぀たり、 u8をu32キャストできたす。 Fromを䜿甚したすが、その逆は䜿甚したせん。

「損倱がない」ずは、収たるほど小さい倀をキャストするこずを意味したす。 䟋 1_u64 as u8は損倱がないため、 u8 as u64 as u8は損倱がありたせん。 フロヌトの堎合、 20000000000000000000000000000_u128 as f32は損倱がないのに察し、 20000001_u32 as f32は損倱がないため、「適合」の簡単な定矩はありたせん。したがっお、 float as intもint as floatも損倱がありたせん。

ただし、 256u64 as u8は損倱がありたす。

しかし、 <anything>_u8 as u64 as u8はそうではありたせん。

喪倱感は正垞であり、ギプスで予想されるものであり、問​​題ではないず思いたす。 キャストを䜿甚した敎数の切り捚お䟋 u32 as u8 は、私が知っおいるすべおのCのような蚀語で䞀貫しおいる、よく理解されおいる意味を持぀䞀般的な操䜜です少なくずも、2の補数の敎数衚珟を䜿甚するアヌキテクチャでは基本的に最近はそれらすべおです。 有効な浮動小数点倉換぀たり、積分郚分が宛先に適合する堎合にも、十分に理解され、合意されたセマンティクスがありたす。 1.6 as u32は䞍可逆ですが、私が知っおいるすべおのCに䌌た蚀語は、結果が1になるはずであるこずに同意しおいたす。 -キャストする蚀語のように、「自分が䜕をしおいるのか知っおいる」皮類の挔算子である高性胜でなければなりたせん。

したがっお、無効な浮動小数点倉換ず同じように問題があるず考える必芁はないず思いたす。Cのような蚀語やハヌドりェアで合意されたセマンティクスがないためですただし、通垞ぱラヌ状態になりたすたたはハヌドりェアの䟋倖、ほずんどの堎合私の経隓ではバグを瀺しおいるため、通垞、正しいコヌドには存圚したせん。

この問題が発生しただけで、再コンパむルしなくおも実行間で再珟できない結果が生成されたす。 このような堎合、 as挔算子はメモリからガベヌゞをフェッチするようです。

個人的には、倉換が無効な堎合にのみ発生し、ガベヌゞ倀を生成する以倖に副䜜甚がない限り、問題ないず思いたす。 コヌドの䞀郚で無効な倉換が本圓に必芁な堎合は、必芁ず思われるセマンティクスを䜿甚しお、無効なケヌスを自分で凊理できたす。

ガベヌゞ倀を生成する以倖に副䜜甚はありたせん

副䜜甚は、ガベヌゞ倀がメモリのどこかで発生し、いく぀かのおそらく機密性の高いデヌタを明らかにするこずです。 float自䜓からのみ蚈算された「ランダム」倀を返すこずは問題ありたせんが、珟圚の動䜜はそうではありたせん。

有効な浮動小数点倉換぀たり、積分郚分が宛先に適合する堎合にも、十分に理解され、合意されたセマンティクスがありたす。

明瀺的なtrunc() 、 round() 、 floor()たたはceil()䌎わないfloatからintぞの倉換のナヌスケヌスはありたすか asの珟圚の䞞め戊略は「未定矩」であり、 asは䞞められおいない数倀にはほずんど䜿甚できたせん。 ほずんどの堎合、 x as u32を曞いおいる人は、実際にはx.round() as u32望んでいるず思いたす。

喪倱感は正垞であり、ギプスで予想されるものであり、問​​題ではないず思いたす。

私は同意したすが、損倱が簡単に予枬できる堎合に限りたす。 敎数の堎合、䞍可逆倉換の条件は明らかです。 フロヌトの堎合、それらはあいたいです。 非垞に倧きな数の堎合は損倱がありたせんが、小さい数の堎合は䞞くおも損倱がありたす。 私の個人的な奜みは、誀っお䞍可逆倉換を導入するこずを避けるために、䞍可逆倉換ず可逆倉換の2぀の異なる挔算子を䜿甚するこずですが、損倱があるかどうかを刀断できる堎合は、1぀の挔算子だけでも問題ありたせん。

副䜜甚は、ガベヌゞ倀がメモリのどこかで発生し、いく぀かのおそらく機密性の高いデヌタを明らかにするこずです。

宛先を倉曎せずにそのたたにしおおくこずを期埅したすが、それが本圓に問題である堎合は、最初にれロにするこずができたす。

明瀺的なtrunc、round、floor、たたはceilを䌎わないfloatからintぞの倉換のナヌスケヌスはありたすか asの珟圚の䞞め戊略は「未定矩」であり、䞞められおいない数倀にはほずんど䜿甚できたせん。

䞞め戊略が本圓に定矩されおいない堎合、それは私にずっお驚きです。すでに敎数を指定しおいない限り、挔算子はほずんど圹に立たないこずに同意したす。 れロに向かっお切り捚おられるず思いたす。

ほずんどの堎合、 x as u32を曞いおいる人は、実際にはx.round() as u32望んでいるず思いたす。

ドメむンにもよるず思いたすが、 x.trunc() as u32もかなり䞀般的に望たれおいるず思いたす。

私は同意したすが、損倱が簡単に予枬できる堎合に限りたす。

私は間違いなく同意したす。 たずえば、 1.6 as u32が1になるか2になるかは未定矩ではありたせん。

https://doc.rust-lang.org/nightly/reference/expressions/operator-expr.html#type -cast-expressions

フロヌトから敎数にキャストするず、フロヌトはれロに向かっお䞞められたす
泚珟圚、䞞められた倀をタヌゲットの敎数型で衚すこずができない堎合、これにより未定矩の動䜜が発生したす。 これには、InfずNaNが含たれたす。 これはバグであり、修正される予定です。

メモはここにリンクしおいたす。

「適合する」倀の䞞めは明確に定矩されおいたすが、それはこの問題の目的ではありたせん。 このスレッドはすでに長いので、すでに確立され文曞化されおいる事実に぀いおの接線を掚枬するこずにそれを取り入れないのは良いこずです。 ありがずう。

決定する必芁があるのは、次の堎合にf as $Intを定矩する方法です。

  • f.trunc() > $Int::MAX 正の無限倧を含む
  • f.trunc() < $Int::MIN 負の無限倧を含む
  • f.is_nan()

Nightlyで-Z saturating-castsコンパむラフラグを䜿甚しおすでに実装され利甚可胜なオプションの1぀は、それぞれを返すように定矩するこずです $Int::MAX 、 $Int::MIN 、およびれロ。 ただし、他の動䜜を遞択するこずは可胜です。

私の芋解では、動䜜は間違いなく決定論的であり、たずえばパニックではなく敎数倀を返す必芁がありたすが、正確な倀はそれほど重芁ではなく、これらのケヌスを気にするナヌザヌは、私が個別に提案しおいる倉換方法を䜿甚する必芁がありたす远加 https 

ドメむンにもよるず思いたすが、 x.trunc() as u32もかなり䞀般的に望たれおいるず思いたす。

正しい。 䞀般に、 x.anything() as u32 、おそらくround()ですが、 trunc() 、 floor() 、 ceil()たす。 具䜓的な䞞め手順を指定せずにx as u32だけで、間違いである可胜性が高くなりたす。

私の芋解では、動䜜は確実に決定論的であり、たずえばパニックではなく敎数倀を返す必芁がありたすが、正確な倀はそれほど重芁ではありたせん

「未定矩」の倀でも、フロヌト自䜓に䟝存せず、最も重芁なこずずしお、無関係なレゞスタずメモリの内容を公開しない限り、個人的には問題ありたせん。

Nightlyで-Z saturating-castsコンパむラフラグを䜿甚しおすでに実装され利甚可胜なオプションの1぀は、それぞれを返すように定矩するこずです $Int::MAX 、 $Int::MIN 、およびれロ。 ただし、他の動䜜を遞択するこずは可胜です。

f.trunc() > $Int::MAXずf.trunc() < $Int::MINで期埅される動䜜は、浮動小数点数の虚数が無限サむズの敎数に倉換され、その最䞋䜍ビットが返される堎合ず同じです敎数型の倉換のように。 技術的には、これは指数に応じお巊にシフトされた有意のビットになりたす正の数の堎合、負の数は2の補数に埓っお反転する必芁がありたす。

したがっお、たずえば、非垞に倧きな数が0に倉換されるこずを期埅したす。

無限倧ずNaNが䜕に倉換されるかを定矩するのは難しい/より恣意的であるように思われたす。

WebAssemblyは、次のセマンティクスで飜和キャストを安定させたした。

https://github.com/WebAssembly/nontrapping-float-to-int-conversions/blob/master/proposals/nontrapping-float-to-int-conversion/Overview.md#design

@CryZeだから、私がそれを正しく読んだら、それは-Z saturating-casts そしおMiriがすでに実装しおいるものず䞀臎したすか

@RalfJungその通りです。

玠晎らしいです。https//github.com/WebAssembly/testsuite/blob/master/conversions.wast トラップを指定された結果に眮き換えおをMiriのテストスむヌトにコピヌし

@RalfJung最新バヌゞョンのconversions.wastに曎新しおください。これは、新しい飜和倉換挔算子のテストを含むように曎新されたばかりです。 新しい挔算子の名前には「_sat」が含たれおおり、トラップがないため、䜕も眮き換える必芁はありたせん。

@sunfishcode曎新しおくれおありがずう ずにかくテストをRustに倉換する必芁があるので、ただ倚くのものを眮き換える必芁がありたす。 ;

_satテストは、テストされる倀に関しお䜕か違いがありたすか 線集倀が同じであるずいうコメントがありたす。Rustの飜和キャストに぀いおは、これらの倀の倚くを取埗しおhttps://github.com/rust-lang/miri/pull/1321に远加したした

UB組み蟌みの堎合、wasm偎のトラップは、Miriでのコンパむル倱敗テストになるはずです。

入力倀はすべお同じですが、唯䞀の違いは、 _sat挔算子が、トラップ挔算子がトラップを予期しおいる入力で出力倀を期埅しおいるこずです。

MiriしたがっおRust CTFE゚ンゞンのテストがhttps://github.com/rust-lang/miri/pull/1321に远加されたしたrustc -Zmir-opt-level=0 -Zsaturating-float-castsもそのファむルのテストに合栌するこずをロヌカルで確認したした。
たた、Miriにチェックされおいない組み蟌み関数も実装したした。https//github.com/rust-lang/miri/pull/1325を参照しお

https://github.com/rust-lang/rust/pull/71269#issuecomment -615537137を投皿したした

このスレッドの長さを考えるず、コメントの内容を芋逃しおいるず思われる堎合は、PRにコメントを送るか、マむナヌな堎合は、ZulipたたはDiscordsimulacrumで気軜にpingしおください。 PRスレッドでの䞍芁なノむズを避けるために問題を修正したす。

蚀語チヌムの誰かがすぐにそのPRでFCP提案を開始し、それをマヌゞするずこの問題が自動的に解決されるこずを期埅しおいたす:)

チェックされたコンバヌゞョンの蚈画はありたすか fn i32::checked_from(f64) -> Result<i32, DoesntFit>ようなもの

i32::checked_from(4.5)䜕を返すかを怜蚎する必芁がありたす。

このペヌゞは圹に立ちたしたか
0 / 5 - 0 評䟡