1 名前:デフォルトの名無しさん mailto:sage [2022/05/12(木) 18:28:20.99 ID:cuIcFT6k.net] 公式 https://www.rust-lang.org/ https://blog.rust-lang.org/ https://github.com/rust-lang/rust Web上の実行環境 https://play.rust-lang.org 日本語の情報 https://rust-jp.rs/ ※Rustを学びたい人はまず最初に公式のThe Bookを読むこと https://doc.rust-lang.org/book/ ※Rustを学ぶ際に犯しがちな12の過ち https://dystroy.org/blog/how-not-to-learn-rust ※Rustのasyncについて知りたければ「async-book」は必読 https://rust-lang.github.io/async-book/ ※C++との比較は専用スレへ C++ vs Rust https://mevius.5ch.net/test/read.cgi/tech/1619219089/ ※次スレは原則>>980 が立てること 前スレ Rust part14 https://mevius.5ch.net/test/read.cgi/tech/1644596656/
511 名前:デフォルトの名無しさん [2022/06/06(月) 23:58:37.28 ID:hMQAMrNY.net] >>502 Rust凄いな ジェネリックもOptionも何でも最適化してくれるとは改めてRustの素晴らしさを実感
512 名前:デフォルトの名無しさん mailto:sage [2022/06/07(火) 00:13:51.07 ID:GvuMwmTL.net] >>502 そのやり方で差が出ないのはchecked_addと同じようにcloneが発生するタイプのaddが使われてるからだよ ジェネリックにしても差が出ない場合もあれば差が出る場合もあるということ
513 名前:デフォルトの名無しさん [2022/06/07(火) 00:16:51.98 ID:y2mAB4fu.net] >>502 やはり同じになったか 既に>>478 が指摘しているように元のコードとイテレータ同士で比較ベンチを取ろうとしないから>>475 を怪しいと思ってた ちゃんと比較ベンチすれば最適化されて同じ速さになることを知っての狼藉だったりして
514 名前:デフォルトの名無しさん mailto:sage [2022/06/07(火) 00:17:18.96 ID:YQOkxy3N.net] https://gist.github.com/rust-play/8caca28378745b36aaba5358d2a54fe8 test bench_1 ... bench: 426,714 ns/iter (+/- 5,563) test bench_fast ... bench: 201,510 ns/iter (+/- 2,926) Criterion の使い方が分からなかったのかな
515 名前:デフォルトの名無しさん [2022/06/07(火) 00:19:44.22 ID:y2mAB4fu.net] >>504 どういうこと? 具体的に>>502 の各コードよりも速いコードを書けるってこと? そのコードを示せない限り>>502 のベンチ結果を覆せない
516 名前:デフォルトの名無しさん [2022/06/07(火) 00:35:03.04 ID:z0w37Unr.net] >>506 君は全く別の問題にすり替えて誤魔化している >>502 のようにイテレーター同士でベンチマークをとるべき
517 名前:デフォルトの名無しさん mailto:sage [2022/06/07(火) 00:38:00.86 ID:wvlfxzyf.net] まーたすがすがしいまでの自演だなぁ
518 名前:デフォルトの名無しさん mailto:sage [2022/06/07(火) 00:39:26.17 ID:r6MnfEMB.net] >>507 >>504 の指摘の何が分からないの?
519 名前:デフォルトの名無しさん mailto:sage [2022/06/07(火) 01:10:53.92 ID:YQOkxy3N.net] https://gist.github.com/rust-play/bde9b95f9bfe4de77fad841db30222c7 test bench_1 ... bench: 420,671 ns/iter (+/- 53,102) test bench_fast ... bench: 219,091 ns/iter (+/- 1,147) こんな汚ないことしてまでイテレータになんかしたくないんだけど どうせ次の文句も大体予想付くし
520 名前:デフォルトの名無しさん [2022/06/07(火) 01:35:52.48 ID:gaZATsj9.net] この件はRustにとって重要なことだから口を挟むが、 Rustではジェネリックで書いてもmonomorphizationによって各型で書いた時と同じコードになる。 だから標準ライブラリの大半はジェネリックに書かれている。 そしてSomeなどのOptionは最適化できる時は綺麗に消えるため、 BigIntのchecked_addのように常にSomeを返す時も最適化でOptionは消えると考えられる。 いずれも抽象的に書けるのに動かすとC並に速いというRustの長所である。 つまり、>>502 の結果が出たことはそれらが実証付けられたことになる。 しかし、以前からジェネリックは無駄とか遅いとかRustの長所に反する主張をする人がいるので気になっていた。 今回もRustのジェネリックは遅いと主張するために、 >>506 のように、完全に異なるもの同士を比較したり、 >>511 のように、Rcを返すという別仕様のものにしてまで、ジェネリックは遅いと主張し出した。 反Rustか反ジェネリックの立場なのかもしれないが、そういう捏造や詐欺のようなことはよくない。
521 名前:デフォルトの名無しさん [2022/06/07(火) 01:49:10.77 ID:eprvoL3W.net] >>512 同意
522 名前:デフォルトの名無しさん mailto:sage [2022/06/07(火) 03:36:34.68 ID:hBVbMSyF.net] >>512 ジェネリクスが無駄だの遅いだのはコード生
523 名前:ャの話ではなくてコードのメンテナンスコスト含めた全体の話では 例えば今回ジェネリックなコードで無駄なcloneを避けるためには CheckedAddAssign といった trait を用意し、各整数型に実装するという余計な手間が発生する また、各整数に追加のtraitを実装したとしても固定長の整数型ではすぐに桁あふれしてしまうから、実質BigUintの実装しか意味がないものになる だったら最初からジェネリックにせずBigUintで実装するか、BigUintやBigIntといった桁あふれしない型だけを対象にすればよい ジェネリクスの良さを語りたいならもっと良い例があるんじゃないの [] [ここ壊れてます]
524 名前:デフォルトの名無しさん [2022/06/07(火) 07:03:55.78 ID:/+rlx4fZ.net] >>511 そのコードはイテレータ内部で無理にunwrapしているためこれだけでpanicしてしまう let mut iter = fibonacci_biguint_iter(); let first = iter.next(); let second = iter.next(); 実行結果 thread 'main' panicked at 'called `Option::unwrap()` on a `None` value', src/main.rs:23:30 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace これでは反証コードになっていないので ちゃんとimpl Iterator<Item = BigUint>を返すコードを書いたほうがいい >>514 その無駄なcloneとは何? ベンチ>>502 のジェネリックコードを含めた5つのコードを見てみたが無駄なcloneは見当たらなかった それらよりもベンチで速いコードが出てこない現状をみると無駄は無いのではないか あと、BigUintを使うまでもない需要も多いのだからジェネリックに書かれたコード一つで十分と感じる
525 名前:デフォルトの名無しさん mailto:sage [2022/06/07(火) 08:13:15.84 ID:AZaNrbV3.net] >>503 それはLLVMのおかげじゃない? 他言語でできないRustならではの優位点てあったっけ?
526 名前:デフォルトの名無しさん mailto:sage [2022/06/07(火) 08:54:11.67 ID:99FzOzNU.net] Rustで抽象オブジェクト作るのってどうやんの?
527 名前:デフォルトの名無しさん mailto:sage [2022/06/07(火) 08:59:47.84 ID:do0qCmU/.net] >>517 Box<dyn ...>のこと?
528 名前:デフォルトの名無しさん mailto:sage [2022/06/07(火) 11:56:38.96 ID:99FzOzNU.net] >>518 C系だと構造体にtypeフィールド作って定数入れてその定数の値に応じて呼び出す関数変えるみたいなことやるんだけど インタプリタの動的オブジェクトみたいなもの Rustでもtypeフィールで条件分岐するのが普通?
529 名前:デフォルトの名無しさん mailto:sage [2022/06/07(火) 12:28:57.89 ID:do0qCmU/.net] >>519 その用法ならたぶんenumですかね https://doc.rust-jp.rs/book-ja/ch06-01-defining-an-enum.html
530 名前:デフォルトの名無しさん mailto:sage [2022/06/07(火) 12:30:31.93 ID:mvWCmBcR.net] ファントムなんとかを使うんじゃないのか?
531 名前:デフォルトの名無しさん [2022/06/07(火) 12:50:46.76 ID:1EDCqMQN.net] 抽象オブジェクトと検索して出てくる例みたいなのをRustでやるならこうだな enum Object { Integer(i32), Float(f32), 文字列(String), Null, } use Object::{Integer, Float, 文字列, Null}; impl Object { fn hello(&self) { match self { Integer(i) => println!("Hello, Intger {i} です"), Float(f) => println!("Hello, Float {f} です"), 文字列(s) => println!("こんにちは、文字列 {s} です"), Null => println!("Nullです"), } } } fn main() { let object_list = [Integer(12345), Float(67.89), 文字列("ABC".into()), Null]; for object in &object_list { object.hello(); } }
532 名前:デフォルトの名無しさん mailto:sage [2022/06/07(火) 13:15:30.50 ID:1v+TnHgu.net] gccではなくg++とかだとフィボナッチ数列とかは演算しないように最適化される場合がある。 Rustのようにイグノーベルの遊びのコンピューターサイエンスのようなコードをこねくり回して気持ち悪く長くて自己満足オナニーコードになるぐらいだったら 部分的にmasmで書いたほうがマシ(速度的にも、メンテナンス性も) またRustはLLVMに執着しすぎてgccのような最適化はまだされてない、フィボナッチ数列とかのしょーもない一般的なアルゴリズムは CPUキャッシュに乗るのにマシンコードのセクションの結果が64kbに成らなかったり
533 名前:デフォルトの名無しさん mailto:sage [2022/06/07(火) 13:48:18.23 ID:99FzOzNU.net] >>620-522 ありがとう
534 名前:デフォルトの名無しさん [2022/06/07(火) 14:15:55.18 ID:uuz77ncq.net] >>523 演算しないように最適化されるとか意味不明 演算はどこかで必ず発生する コンパイル時点で演算してしまう定数化のことならばRustでも当然できる const fn fibonacci(n: usize) -> usize { const fn f(n: usize, a: usize, b: usize) -> usize { match n { 0 => a, 1 => b, _ => f(n - 1, b, a + b), } } f(n, 0, 1) } const F77: usize = fibonacci(77);
535 名前:デフォルトの名無しさん mailto:sage [2022/06/07(火) 15:36:32.04 ID:glYADNck.net] >>511 俺環の遅いマシンだと6倍近く速くなった この差なら用途によっては汚くする価値が十分あるね まあ実際のプログラムでBigUintのサイズまで一つ一つイテレータで返すような使い方をすることはまずないだろうけど
536 名前:デフォルトの名無しさん [2022/06/07(火) 15:42:23.15 ID:fRg0KLfu.net] >>511 コードが汚い上にget_mutが失敗してpanicする欠陥コードを恥ずかしげもなく披露できるもんだな
537 名前:デフォルトの名無しさん mailto:sage [2022/06/07(火) 17:49:46.06 ID:jaUMaLrL.net] >>525 だからそう言ってる、そして機能紹介は知ってることを言わなくてよいよ?コンパイル時実行とは違う。gcc系は数学的に既に答えが出るようなアルゴリズムを書いた場合に演算しないで低い桁で答えを持つ場合がある。 意味が分からないんだったら日本語から勉強しなおせ。それと汚いものを張り付けるな
538 名前:デフォルトの名無しさん mailto:sage [2022/06/07(火) 18:06:57.96 ID:WAenZnu4.net] >>523 定数たたみ込みのことかな 試した限りでは gcc でも clang でも rustc でも最適化されて fib 呼び出しは消えているよ どういうコードで問題おきるの? gcc: https://godbolt.org/z/nx3hnsxTT clang: https://godbolt.org/z/MYc7G9jeG rustc: https://godbolt.org/z/x18ob3MjP
539 名前:デフォルトの名無しさん mailto:sage [2022/06/07(火) 18:10:22.54 ID:WAenZnu4.net] >>523 あとrustがllvmに執着しているというのも間違いで gccのcodegenを使えるようにするプロジェクトもあって活発に開発されてるよ https://github.com/rust-lang/rustc_codegen_gcc
540 名前:デフォルトの名無しさん [2022/06/07(火) 18:17:47.44 ID:1EdYDqGn.net] >>524 >>620 よろすく
541 名前:デフォルトの名無しさん mailto:sage [2022/06/07(火) 20:22:53.88 ID:UaJ7fd+W.net] フィボナッチなんて普通に解析解あるんだからそれ使えばいいじゃん
542 名前:デフォルトの名無しさん mailto:sage [2022/06/07(火) 20:28:59.38 ID:ZSCymycr.net] フィボナッチよりボイニッチを解読してくれ
543 名前:デフォルトの名無しさん mailto:sage [2022/06/07(火) 23:19:58.58 ID:bfW1tdFv.net] ボイニッチはどうせ創作ノートでしかないし
544 名前:デフォルトの名無しさん [2022/06/07(火) 23:25:02.45 ID:lnwubCy8.net] >>532 フィボナッチは単なる題材に過ぎないことを理解できていないのはヤバいぞ 例えば>>529 の定数畳み込みや>>502 のジェネリックやOptionが最適化される話などが本題 単純だが単純過ぎない題材の例としてたまたまフィボナッチ数列が使われている
545 名前:デフォルトの名無しさん mailto:sage [2022/06/07(火) 23:57:19.63 ID:YQOkxy3N.net] ワッチョイありスレに移住してここは複おじに明け渡してやったほうがいいのかもな
546 名前:デフォルトの名無しさん mailto:sage [2022/06/08(水) 00:55:31.29 ID:QhxBwpDW.net] >>536 複おじの意味がいまだにわからないが ジェネリックよりも速いコードがあるならきちんと示そうぜ >>506 はイテレータと関数の異種比較のイカサマ >>511 はイテレータ同士の比較へ改善されたがイテレータの中のunwrapでpanicするマガイモノ そんなデタラメばかりしていたら信頼を失うぜ
547 名前:デフォルトの名無しさん mailto:sage [2022/06/08(水) 01:35:00.04 ID:jyTDsLRS.net] >>537 >>481 は?
548 名前:デフォルトの名無しさん mailto:sage [2022/06/08(水) 01:40:47.24 ID:C5b6ywPX.net] https://play.rust-lang.org/?version=nightly&mode=release&edition=2021&gist=5180fadf9fda409e0456042fc1bccd8e 遅くなるの分かりきってたから出し渋ったつもりだったけど普通に速かったわwwwメンゴメンゴ test bench_1 ... bench: 426,277 ns/iter (+/- 1,804) test bench_fast ... bench: 350,928 ns/iter (+/- 2,760) 一応criterion版も貼っとく >>502 で提起されたベンチマーク不適切説の真偽が気になるなら是非実行してみてくれ https://gist.github.com/rust-play/3bd45555b9e6faef2b1426712e4e7601
549 名前:デフォルトの名無しさん mailto:sage [2022/06/08(水) 02:05:38.58 ID:jyTDsLRS.net] >>539 はin-placeなchecked_addを実現するtraitがないことで速度差大きくなってるものだよね ジェネリクスが遅いと言ったときに、 ジェネリクスの機構自体による速度差と、ジェネリクスにまつわるエコシステムによる速度差という二通りの解釈があると思うけど、 >>537 は前者のことを、>>539 は後者のことを言っていて議論がかみ合っていないのではないか ジェネリクスの機構だけの話をするなら前者の議論だけで良いけど、 メンテナンスコスト含めた実用性考えると後者の範囲も考える必要があるよね、 というのが>>514 で言いたかったこと
550 名前:デフォルトの名無しさん mailto:sage [2022/06/08(水) 02:17:57.20 ID:aUi5KtMm.net] >>539 君のベンチはいつも何と何の違いを比較しようとしているのかよくわからない 一方で>>502 は何と何を比較するのかを明確にした上で各項目毎に段階を経て比較しているから 仮にベンチで違いがあればその要因が明確となり知見が得られる比較となっている 君の投稿からは結果に対して何が要因なのか知見が全く得られない
551 名前:デフォルトの名無しさん mailto:sage [2022/06/08(水) 02:29:17.13 ID:aUi5KtMm.net] >>540 まず速度差がそのおっしゃっているchecked_addによるものなのかどうかを明確にしたほうが良いかと思う >>502 を見てみると(2)→(3)がchecked_addの有無になっているがベンチは同じ その結果からchecked_addは関係ないのではないか?
552 名前:デフォルトの名無しさん mailto:sage [2022/06/08(水) 04:21:09 ID:uEpi8n1p.net] >>540 ジェネリックにやりたいならCheckedAddAssignを作ればいいんじゃん? Rcのもジェネリックにもできるわけだし
553 名前:デフォルトの名無しさん mailto:sage [2022/06/08(水) 05:52:38 ID:78wIRTgY.net] >>540 そもそもコードが汚いという指摘が発端なので 前者が論点だと思ってる人はいないと思うよ
554 名前:デフォルトの名無しさん mailto:sage [2022/06/08(水) 06:22:34.20 ID:2tL4qRNc.net] >>544 元と同一コードを含む5種類のベンチ>>502 のコードを見たけど 特に汚いコードは見当たらないんじゃない? もしあるならば具体的にどの部分なのかを言ったほうがいいと思うよ
555 名前:デフォルトの名無しさん mailto:sage [2022/06/08(水) 08:45:07.60 ID:C5b6ywPX.net] >>541 「checked_addしてから代入」と「add_assign」の比較だよ で現状後者はジェネリックにやるために適切なtraitが無いから、 ジェネリックな関数では性能向上に限界があるよねって話 >>540 の言う通り、ジェネリック関数とmonomorphized関数をの性能を比較したいわけじゃないよ >>542 >>490 ,491でも出た通り、checked_addとadd(両辺とも参照の場合)はどっちもcloneが発生する だから(2)を(3)にしても、遅いchecked_addを遅いaddで置き換えただけなので性能向上は無い あとclone発生してるのはここね、docs.rsの[src]からたどれば&BigUint同士のaddがこのマクロで定義されているのが分かるはず https://docs.rs/num-bigint/latest/src/num_bigint/macros.rs.html#91-107
556 名前:デフォルトの名無しさん mailto:sage [2022/06/08(水) 09:03:01.17 ID:C5b6ywPX.net] あんまり頑固になっても聞かなさそうなんでそろそろ妥協案でも どうしてもジェネリックでやりたかったら、num::PrimIntでも使ってればここまでの批判は無かったんじゃないですかね BigUint/BigIntは範囲から外れるけど、それはやっぱりそういうものなんですよ
557 名前:デフォルトの名無しさん mailto:sage [2022/06/08(水) 09:13:21.45 ID:2tL4qRNc.net] >>546 あなたのコード>>539 もclone()しているから 1回あたりclone()が1回発生している点で同じではないかね そこは重要なところだから曖昧な推測で済ませずに細かい差異でベンチマークを取ったほうがいいのではないか
558 名前:デフォルトの名無しさん mailto:sage [2022/06/08(水) 11:26:56.36 ID:oyhrGaRU.net] Rustが自由自在に書けるようなプログラマになりたがったンゴねえ ワイは低脳だから躓いてるンゴ 例えば&'static TとT: 'staticの違いがなんかあるらしいんやがわからなかったンゴ 前者はプログラム終了時まで生きる変数の参照って意味で後者はもしTに参照があったらそれは'static以上生きるって解釈であってるんか?
559 名前:デフォルトの名無しさん mailto:sage [2022/06/08(水) 11:49:32.36 ID:oyhrGaRU.net] いや理解したんご 前者は参照型しか受け付けないけど後者はそれ以上の種類の型を受け付けるンゴねえ さらに違いがあるかもだけど勉強進めるわ なんでもなかった
560 名前:デフォルトの名無しさん mailto:sage [2022/06/08(水) 12:37:42.94 ID:C5b6ywPX.net] >>548 そのベンチが>>539 のつもりなんだけど、これにどういう問題があって具体的には何をしろと? from_fn使ってる分(5)のほうが近いから比較対象を(1)から(5)に変えろってこと? というかそれが分かっているなら他人にやらせるんでなく自分で検証すればいいのでは?
561 名前:デフォルトの名無しさん mailto:sage [2022/06/08(水) 14:46:42.18 ID:JNpA1ROM.net] >>551 結局、何が原因なん? ジェネリック?それともchecked_add?あるいは変数Some?まさかのswap? Rustスレとしてはコードよりも原因を知りたい
562 名前:デフォルトの名無しさん mailto:sage [2022/06/08(水) 15:00:02.66 ID:0R8j40RZ.net] >>502 「1.5倍も差があるのは妙だな Rustでは最適化されるのでジェネリックで書こうがそんな差は出ないはず」 これがそもそもおかしい、最適化されようが何だろうが生成されるコードは違うのでMIRなりdisamなりでインストラクション単位で目視すれば一発だろ。ベンチを取る以前の思い込み低レベルな話 そしてほぼ最適化された無駄のないコードだったとしても >>523 ここ5年程度のCPUでは64バイトのDSB境界を持つ小さなループ呼び出しなどが単一のμopsキャッシュに収まる場合があるがコードの配置によって異なり1.5倍程度の差が出ても不思議じゃない。 言ってるのに全く聞かない
563 名前:デフォルトの名無しさん mailto:sage [2022/06/08(水) 15:48:23.76 ID:kiLfNcoT.net] >>553 その件は1.5倍差あった>>481 がイテレータと関数を比較するという大チョンボをしていたことが原因と判明済 そしてジェネリックか否か自体では速度に差が出ないことを>>502 のベンチが証明済
564 名前:デフォルトの名無しさん mailto:sage [2022/06/08(水) 17:10:39.22 ID:C5b6ywPX.net] >>554 よく見ろ、それは>>475 の話だ >>481 は両方とも(usize) -> BigUintな関数
565 名前:デフォルトの名無しさん mailto:sage [2022/06/08(水) 17:16:08.77 ID:LlAtoLIj.net] これだけ時間をか
566 名前:けても原因すら分からずノンジェネリックとの速度差を埋められない状況をコストとして認識できてないのが恐ろしい [] [ここ壊れてます]
567 名前:デフォルトの名無しさん mailto:sage [2022/06/08(水) 17:31:51.50 ID:H0oyRmek.net] 一般的に、数列を順に求めるイテレータと、 そのうちの特定の数だけを求める関数とでは、 オーダー問題もアルゴリズムも変わってくるため、 >>481 はまた別の問題となっている。 イテレータ同士の比較で1.5倍となっていないことからも、 異なる問題であると理解できるはず。 >>556 ジェネリックとノンジェネリックに速度差が無いことは、 >>502 で既に示されたのだから、 ジェネリックかどうかは一切関係ないと思う。 ジェネリックとは別の問題。
568 名前:デフォルトの名無しさん mailto:sage [2022/06/08(水) 18:18:03.20 ID:cKPONsWM.net] >>557 >>502 はジェネリックでも実現できるコードをノンジェネリックにしただけ ノンジェネリックならadd_assign, mem::swap, cloneで>>502 のいずれよりも速いコードが書けるが ジェネリックだとchecked_addを使わざるを得ず同じことが実現できない
569 名前:デフォルトの名無しさん mailto:sage [2022/06/08(水) 18:32:47.55 ID:y1p7Fxu2.net] >>537 では「ジェネリックよりも速いコードがあるならきちんと示そうぜ」と言っていて >>540 の言う違いを理解している感じだったのに いざ本当にコードが出てくるとジェネリクス自体のオーバーヘッドの話に限定して、差は無いと連呼 わざとやってんの?
570 名前:デフォルトの名無しさん mailto:sage [2022/06/08(水) 19:11:11 ID:sj9oTS9C.net] >>558 > ジェネリックだとchecked_addを使わざるを得ず同じことが実現できない それは違うのではないか? ジェネリックでも自由にCheckedAddAssign等を定義して実現することが可能という話が既に出ている >>492 >>543 一方でノンジェネリックで書いてもオーバフロー対策としてchecked_addは使わざるを得ない つまりどちらが有利とか優れているとかいう問題ではない
571 名前:デフォルトの名無しさん mailto:sage [2022/06/08(水) 19:45:52.60 ID:btlg3B6B.net] >>560 他人の意見を鵜呑みにしてないでやってみれば? 俺はちょっと試してみたけど結局無理だと確信したよ
572 名前:デフォルトの名無しさん mailto:sage [2022/06/08(水) 19:54:30.37 ID:hF0KVPZD.net] CheckedAddAssignの定義難しいよね cloneを減らせるうまい定義見せて欲しい
573 名前:デフォルトの名無しさん mailto:sage [2022/06/08(水) 19:58:01.42 ID:hF0KVPZD.net] >>560 > 一方でノンジェネリックで書いてもオーバフロー対策としてchecked_addは使わざるを得ない つまりどちらが有利とか優れているとかいう問題ではない BigUintの場合はオーバーフローを想定しなくて良いからただのAddAssignで良いよね ジェネリックな実装の場合は考慮すべき事項が増えるというハンデを抱えている
574 名前:デフォルトの名無しさん mailto:sage [2022/06/08(水) 20:09:35.76 ID:Pauu0yN9.net] 基地同士の喧嘩おもすれー
575 名前:デフォルトの名無しさん mailto:sage [2022/06/08(水) 21:16:33.76 ID:zfNTYu3X.net] ジェネリックでなくても各i8版~u128版でchecked_add要るんじゃね?
576 名前:デフォルトの名無しさん mailto:sage [2022/06/08(水) 21:31:30.99 ID:uKz/tAPi.net] >>560 CheckedAddAssignはAddAssignと同じようには実現できないよ 速度差は他の方法で工夫すれば埋めることは不可能ではない
577 名前:デフォルトの名無しさん mailto:sage [2022/06/08(水) 22:52:52.99 ID:C5b6ywPX.net] このままでは誰も気付かなさそうなのでここでネタばらし >>539 のcriterion版ですがこちらで動かすとこうなりました fibonacci_iter_1 time: [7.3605 ms 7.3655 ms 7.3711 ms] Found 9 outliers among 100 measurements (9.00%) 1 (1.00%) high mild 8 (8.00%) high severe fibonacci_biguint_iter time: [7.5944 ms 7.5967 ms 7.5992 ms] Found 2 outliers among 100 measurements (2.00%) 1 (1.00%) high mild 1 (1.00%) high severe 同程度に遅くなってしまいました 理由は>>548 の通り、せっかく減らしたcloneをイテレータ化するために戻さざるを得なかったからです 一見非ジェネリックのほうが速い結果が出たのは、criterion版がN=50000としていたのに対して、 test crate版は最初に貼られたN=10000から変えずにやっていたためでした criterion版をN=10000で、test crate版をN=50000で計測してみると大体同じような結果になりました N<2^15あたりまでは非ジェネリックのほうがちょっとだけ速いみたいですが、まあ誤差の範疇かと思います そういうわけで>>539 で非ジェネリックのほうが速いと主張したのは嘘です 本気で信じちゃった人はごめんね 最初はcriterionとtest crateの差だと早とちりしたため、ベンチマーク不適切説とか勿体ぶった書き方をしてました >>502 で根拠も無く疑いをかけたのに対するカウンターのつもりで黙ってたんですが、不発になっちゃいました まあでもtest crateってwarm upもしないしサンプル数固定だし、その結果ひどい場合だと>>511 なんか相対誤差10%超えてるし criterion使ったほうがいいよってのは大筋では間違ってないよね 最後に+=でイテレートするこれだけ貼っとくから 某おじはこれに相当する性能のジェネリックなイテレータが書けるまでそういったクソどうでもいい執着に人を付き合わせるんじゃないぞ https://play.rust-lang.org/?version=stable&mode=release&edition=2021&gist=76cd0aad53f19888900a4b450fd078c5
578 名前:デフォルトの名無しさん mailto:sage [2022/06/08(水) 23:10:54.19 ID:Pauu0yN9.net] Rust使うやつは全員クズ
579 名前:デフォルトの名無しさん mailto:sage [2022/06/08(水) 23:14:19.56 ID:xZpQpCco.net] ゴミみてぇに使いにくい
580 名前:デフォルトの名無しさん mailto:sage [2022/06/08(水) 23:33:46.23 ID:1Qgkgfnu.net] >>567 ジェネリックは遅くて使い物にならずRustはクソ言語のいい流れが出来ていたのに邪魔すんなボケ
581 名前:デフォルトの名無しさん mailto:sage [2022/06/09(木) 00:05:50.09 ID:8AO4ag5u.net] >>567 それが本当にベンチマークしたかった内容なのかな? Nの変化による性能差の変化が重要 Rcでイテレータ返すやつと合わせて確認すればN=50000だと差がなくなる理由も分かる
582 名前:デフォルトの名無しさん mailto:sage [2022/06/09(木) 01:08:31 ID:b8HehfnZ.net] >>567 裏切り者め 隠し通せよ
583 名前:デフォルトの名無しさん mailto:sage [2022/06/09(木) 09:43:05.84 ID:m8hzuB37.net] >>567 結局ジェネリックに書いても非ジェネリックでも速さはほぼ同じなのかよ どんな方法で書いても結果を返すためにclone相当が最低1回は必要で >>502 のジェネリック版はclone相当がchecked_addでの1回のみだからこれ以上は速くできないってことか
584 名前:デフォルトの名無しさん mailto:sage [2022/06/09(木) 11:12:09.28 ID:5tn+SNbG.net] 複オジ必死やなw
585 名前:デフォルトの名無しさん mailto:sage [2022/06/09(木) 11:39:59.58 ID:gQa8Lild.net] iterなんだけど let v = vec![1, 2, 3, 4]; v.iter().filter(|&x| x % 2 == 0).cloned().collect(); v.iter().map(|&x| x * 2).collect(); filter()はcloned()が必要でなぜmap()は必要ないのか
586 名前:デフォルトの名無しさん mailto:sage [2022/06/09(木) 11:41:07.83 ID:gQa8Lild.net] まちがえたこうだ let v = vec![1, 2, 3, 4]; let result_1 = v.iter().filter(|&x| x % 2 == 0).cloned().collect(); let result_2 = v.iter().map(|&x| x * 2).collect();
587 名前:デフォルトの名無しさん mailto:sage [2022/06/09(木) 11:52:52.81 ID:WWB1ag70.net] >>573 IteratorのItem生成のためにcloneが必要という話なので 参照返すとかRc<RefCell>にするとかすればまだ改善する余地はありそうではある
588 名前:デフォルトの名無しさん mailto:sage [2022/06/09(木) 14:32:02.03 ID:BXa7hn4f.net] 「Atom」の開発者が究極のコードエディターを目指す ~「Zed」の開発が始動 「Electron」を捨て、Rust言語を採用。GPUI、tree-sitterなどで武装し、超高速なコードエディターに https://forest.watch.impress.co.jp/docs/serial/yajiuma/1374986.html
589 名前:デフォルトの名無しさん mailto:sage [2022/06/09(木) 14:58:44.89 ID:G7q6UoxI.net] 「重要」でスレ内検索かけると……
590 名前:デフォルトの名無しさん mailto:sage [2022/06/09(木) 16:58:07.35 ID:/uOnDbzK.net] >>575 Vec<i32>のiter()は&i32のイテレータ filterした結果も&i32なのでVec<i32>でcollectしたければcopiedやclonedが必要 Vec<&i32>のままcollectするならclonedは不要 mapの例はx * 2でi32が新たに生成され map以降は&i32ではなくi32のイテレータになるので cloned無しでVec<i32>にcollectできる
591 名前:デフォルトの名無しさん mailto:sage [2022/06/09(木) 17:07:43.03 ID:3qzGL8h6.net] >>577 Rc版はmake_mutにすれば呼び出し側が参照をつかんでる時だけcloneにフォールバックしてくれる つかんでなければcloneしないので高速 全ての値をつかむようならRcを使わないやり方より少し遅くなる
592 名前:デフォルトの名無しさん mailto:sage [2022/06/09(木) 20:30:30.68 ID:sXhLSFat.net] >>355 はRustだと末尾呼び出しの最適化が効くの? 末尾呼び出し最適化必須のschemeですら自動的には最適化されず、人間が意味を解析して、アキュムレーター使って末尾再帰になるようにしましょうって練習問題になるくらいなのに。 Rust凄い!!
593 名前:デフォルトの名無しさん mailto:sage [2022/06/09(木) 21:24:26.48 ID:xbJg8ij+.net] >>581 簡易的なstreaming iteratorにする方法もあるよ
594 名前:はちみつ餃子 mailto:sage [2022/06/09(木) 22:43:27.67 ID:k8dtcEck.net] >>582 どういう理解をしてるのかようわからんが、 >>355 はいわゆる末尾呼出しではないよ。
595 名前:デフォルトの名無しさん mailto:sage [2022/06/10(金) 00:02:10.12 ID:/2sYVq21.net] https://twitter.com/Ray__March/status/1523717266730151936 Crab Rave (deleted an unsolicited ad)
596 名前:582 mailto:sage [2022/06/10(金) 12:26:19.22 ID:xMTaqdcz.net] >>584 340くらいから末尾呼び出し最適化の話題があって、355の2で「リリースモードだとスタックが溢れない」と書いてあったので、末尾呼び出し最適化が効いたのかと思いました。 十分なスタック容量があっただけ? 1+count(n-1) を count(n-1, acc+1) に書き換えてくれる最適化があるのかな、と思いまして
597 名前:デフォルトの名無しさん mailto:sage [2022/06/10(金) 12:39:41.49 ID:awrGQFqA.net] >>586 生成されたバイナリを見た方が良いよ https://godbolt.org/z/Kcd6zf68e 定数たたみ込みでnopになってるっぽい
598 名前:デフォルトの名無しさん mailto:sage [2022/06/10(金) 12:44:00.71 ID:NmVzwec3.net] >>583 ストリーミングイテレータを試してみたけどRc使ったほうが少し速かった ただ呼び出し側が参照をつかんだままにするとコンパイルエラーにしてくれるのでRcより望ましいケースが多々ありそう
599 名前:デフォルトの名無しさん mailto:sage [2022/06/10(金) 13:14:03.27 ID:/2sYVq21.net] streaming iterator! そういうのもあるのか 自分への参照を返せるんだね 使うかどうかは分からんけど覚えておこう
600 名前:582 mailto:sage [2022/06/10(金) 17:55:03 ID:k70t2J8V.net] >>587 すまん
601 名前:はちみつ餃子 mailto:sage [2022/06/10(金) 20:18:18.95 ID:din4Kjb/.net] >>586 すでに >>587 が指摘しているが、定数畳み込みが起こっている。 入力が定数で、かつそれに対する演算が副作用のない基本的なものであった場合に定数畳み込みがされやすい。 定数ではない場合でもこの関数 count は mov rax, rdi ret になってて、入力をそのまま返す形にまで最適化されるので末尾呼出しがどうこうというレベルのものではなくなっている。 最適化というのは、レジスタ割り当てなどは理論的な背景がはっきりしているが、多くの細々としたものは「大量の置き換えパターンを辞書のように持っている」という物量で押し切る泥臭いものだったりするので (それをやりやすいようなデータ構造とかに工夫はあると思うが) 結局のところは投入されたリソースが多いやつが強い。 ちなみに Scheme の末尾呼出し最適化は言語仕様で要求する最低限度がそれだけ (しかし常にやらなければならない) という意味であって、それ以上の最適化をやっちゃ駄目という意味ではないよ。 最適化をどのレベルまでやるかは処理系次第。
602 名前:デフォルトの名無しさん mailto:sage [2022/06/10(金) 20:27:25.22 ID:VliTcE7P.net] こいつが出てくると結論が1つも分からなくなる
603 名前:デフォルトの名無しさん mailto:sage [2022/06/10(金) 21:05:43.32 ID:uz7MKgqc.net] 複オジと同じ臭い
604 名前:デフォルトの名無しさん mailto:sage [2022/06/10(金) 21:45:41.77 ID:iyAWtrh4.net] 汚文章は汚コードの兄弟 同じ親から生まれてくるもの
605 名前:デフォルトの名無しさん mailto:sage [2022/06/10(金) 22:32:01.13 ID:r0Sf5PMX.net] 最適化の話はかなりコンパイラーに詳しくないとなぜそうなるかって分からないだろうからな コンパイラーの最適化について話せる奴はプログラミング中級者以上だろ。 (本職プログラマなら話せないと知識なさすぎと言われるだろうが) 趣味でプの俺は永遠に初心者レベルでそんな知識ないから、こいつ何を言っているんだ?だが
606 名前:デフォルトの名無しさん mailto:sage [2022/06/10(金) 22:32:11.19 ID:+N1EN6wu.net] まぁ要するに ×××という最適化処理が処理系の規格として定められているのなら処理系の開発者(=コンパイラとか作る人)はその最適化を実現しないといけないしそれを利用するプログラマは処理系が”上手いことやってくれる”と期待していい、しかしそれが言語規格上は必須とされてない処理については処理系が“うまいことやつてくれる”と基本は期待してはいけない けど、規格で求められてないような高度な最適化処理を“してはいけない”わけではない、最新の理論で見つかった最適化処理など取り入れる分には好きにして構わない という意味でしょ Haskellのメモ化処理とかでもよく出てくるよ GHCって言うすごい処理系があってHaskellの標準規格では全然定められてないような最適化処理をバンバンやってくれるから“なんでこんなにはやいの?とりま作っただけなのに”と思うこと時々あるからな
607 名前:デフォルトの名無しさん mailto:sage [2022/06/10(金) 22:36:04.99 ID:3HE2W+m8.net] 最適化と言えば&mutがnoaliasになって高速化したコード出会ったことある人居る?
608 名前:デフォルトの名無しさん mailto:sage [2022/06/10(金) 22:56:48.93 ID:/Qg1cUoJ.net] >>596 要するに~ 元の説明より長なっとるやないかーいww 脳みそ整理整頓してこんかーいww
609 名前:デフォルトの名無しさん mailto:sage [2022/06/10(金) 23:03:01.48 ID:EifRM46R.net] >>595 初心者自演乙オジ
610 名前:デフォルトの名無しさん mailto:sage [2022/06/10(金) 23:39:18 ID:QxuEFd4p.net] またいつもと同じパターン 善人 = 情報や説明やコード等を書いてくれる人 悪人 = 文句や批判だけの人 >>597 Rustでは基本的に二つの & mut がaliasになることはないからnoaliasでいいけど LLVMのバグが見つかったりやRustコンパイラの改修などで変遷を経てきてるみたいね > Rust 1.0 ~ 1.7 noalias enabled > Rust 1.8 ~ 1.27 noalias disabled > Rust 1.28 ~ 1.29 noalias enabled > Rust 1.30 ~ 1.54 noalias disabled > Rust 1.54 ~ noalias enabled
611 名前:デフォルトの名無しさん mailto:sage [2022/06/10(金) 23:52:37.74 ID:q3uEdydr.net] 仕様ころころゴミ言語