Rust part15

■ このスレッドは過去ログ倉庫に格納されています
2022/05/12(木) 18:28:20.99ID:cuIcFT6k
公式
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/
2022/06/07(火) 08:59:47.84ID:do0qCmU/
>>517
Box<dyn ...>のこと?
2022/06/07(火) 11:56:38.96ID:99FzOzNU
>>518
C系だと構造体にtypeフィールド作って定数入れてその定数の値に応じて呼び出す関数変えるみたいなことやるんだけど
インタプリタの動的オブジェクトみたいなもの
Rustでもtypeフィールで条件分岐するのが普通?
2022/06/07(火) 12:28:57.89ID:do0qCmU/
>>519
その用法ならたぶんenumですかね
https://doc.rust-jp.rs/book-ja/ch06-01-defining-an-enum.html
2022/06/07(火) 12:30:31.93ID:mvWCmBcR
ファントムなんとかを使うんじゃないのか?
522デフォルトの名無しさん
垢版 |
2022/06/07(火) 12:50:46.76ID:1EDCqMQN
抽象オブジェクトと検索して出てくる例みたいなのを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();
}
}
2022/06/07(火) 13:15:30.50ID:1v+TnHgu
gccではなくg++とかだとフィボナッチ数列とかは演算しないように最適化される場合がある。
Rustのようにイグノーベルの遊びのコンピューターサイエンスのようなコードをこねくり回して気持ち悪く長くて自己満足オナニーコードになるぐらいだったら
部分的にmasmで書いたほうがマシ(速度的にも、メンテナンス性も)
またRustはLLVMに執着しすぎてgccのような最適化はまだされてない、フィボナッチ数列とかのしょーもない一般的なアルゴリズムは
CPUキャッシュに乗るのにマシンコードのセクションの結果が64kbに成らなかったり
2022/06/07(火) 13:48:18.23ID:99FzOzNU
>>620-522
ありがとう
525デフォルトの名無しさん
垢版 |
2022/06/07(火) 14:15:55.18ID:uuz77ncq
>>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);
2022/06/07(火) 15:36:32.04ID:glYADNck
>>511
俺環の遅いマシンだと6倍近く速くなった
この差なら用途によっては汚くする価値が十分あるね

まあ実際のプログラムでBigUintのサイズまで一つ一つイテレータで返すような使い方をすることはまずないだろうけど
527デフォルトの名無しさん
垢版 |
2022/06/07(火) 15:42:23.15ID:fRg0KLfu
>>511
コードが汚い上にget_mutが失敗してpanicする欠陥コードを恥ずかしげもなく披露できるもんだな
2022/06/07(火) 17:49:46.06ID:jaUMaLrL
>>525
だからそう言ってる、そして機能紹介は知ってることを言わなくてよいよ?コンパイル時実行とは違う。gcc系は数学的に既に答えが出るようなアルゴリズムを書いた場合に演算しないで低い桁で答えを持つ場合がある。
意味が分からないんだったら日本語から勉強しなおせ。それと汚いものを張り付けるな
2022/06/07(火) 18:06:57.96ID:WAenZnu4
>>523
定数たたみ込みのことかな
試した限りでは gcc でも clang でも rustc でも最適化されて fib 呼び出しは消えているよ
どういうコードで問題おきるの?

gcc: https://godbolt.org/z/nx3hnsxTT
clang: https://godbolt.org/z/MYc7G9jeG
rustc: https://godbolt.org/z/x18ob3MjP
2022/06/07(火) 18:10:22.54ID:WAenZnu4
>>523
あとrustがllvmに執着しているというのも間違いで
gccのcodegenを使えるようにするプロジェクトもあって活発に開発されてるよ
https://github.com/rust-lang/rustc_codegen_gcc
531デフォルトの名無しさん
垢版 |
2022/06/07(火) 18:17:47.44ID:1EdYDqGn
>>524
>>620 よろすく
2022/06/07(火) 20:22:53.88ID:UaJ7fd+W
フィボナッチなんて普通に解析解あるんだからそれ使えばいいじゃん
2022/06/07(火) 20:28:59.38ID:ZSCymycr
フィボナッチよりボイニッチを解読してくれ
2022/06/07(火) 23:19:58.58ID:bfW1tdFv
ボイニッチはどうせ創作ノートでしかないし
535デフォルトの名無しさん
垢版 |
2022/06/07(火) 23:25:02.45ID:lnwubCy8
>>532
フィボナッチは単なる題材に過ぎないことを理解できていないのはヤバいぞ
例えば>>529の定数畳み込みや>>502のジェネリックやOptionが最適化される話などが本題
単純だが単純過ぎない題材の例としてたまたまフィボナッチ数列が使われている
2022/06/07(火) 23:57:19.63ID:YQOkxy3N
ワッチョイありスレに移住してここは複おじに明け渡してやったほうがいいのかもな
2022/06/08(水) 00:55:31.29ID:QhxBwpDW
>>536
複おじの意味がいまだにわからないが
ジェネリックよりも速いコードがあるならきちんと示そうぜ

>>506はイテレータと関数の異種比較のイカサマ
>>511はイテレータ同士の比較へ改善されたがイテレータの中のunwrapでpanicするマガイモノ
そんなデタラメばかりしていたら信頼を失うぜ
2022/06/08(水) 01:35:00.04ID:jyTDsLRS
>>537
>>481は?
2022/06/08(水) 01:40:47.24ID:C5b6ywPX
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
2022/06/08(水) 02:05:38.58ID:jyTDsLRS
>>539はin-placeなchecked_addを実現するtraitがないことで速度差大きくなってるものだよね

ジェネリクスが遅いと言ったときに、
ジェネリクスの機構自体による速度差と、ジェネリクスにまつわるエコシステムによる速度差という二通りの解釈があると思うけど、
>>537は前者のことを、>>539は後者のことを言っていて議論がかみ合っていないのではないか

ジェネリクスの機構だけの話をするなら前者の議論だけで良いけど、
メンテナンスコスト含めた実用性考えると後者の範囲も考える必要があるよね、
というのが>>514で言いたかったこと
2022/06/08(水) 02:17:57.20ID:aUi5KtMm
>>539
君のベンチはいつも何と何の違いを比較しようとしているのかよくわからない

一方で>>502は何と何を比較するのかを明確にした上で各項目毎に段階を経て比較しているから
仮にベンチで違いがあればその要因が明確となり知見が得られる比較となっている

君の投稿からは結果に対して何が要因なのか知見が全く得られない
2022/06/08(水) 02:29:17.13ID:aUi5KtMm
>>540
まず速度差がそのおっしゃっているchecked_addによるものなのかどうかを明確にしたほうが良いかと思う
>>502を見てみると(2)→(3)がchecked_addの有無になっているがベンチは同じ
その結果からchecked_addは関係ないのではないか?
2022/06/08(水) 04:21:09.02ID:uEpi8n1p
>>540
ジェネリックにやりたいならCheckedAddAssignを作ればいいんじゃん?
Rcのもジェネリックにもできるわけだし
2022/06/08(水) 05:52:38.17ID:78wIRTgY
>>540
そもそもコードが汚いという指摘が発端なので
前者が論点だと思ってる人はいないと思うよ
2022/06/08(水) 06:22:34.20ID:2tL4qRNc
>>544
元と同一コードを含む5種類のベンチ>>502のコードを見たけど
特に汚いコードは見当たらないんじゃない?
もしあるならば具体的にどの部分なのかを言ったほうがいいと思うよ
2022/06/08(水) 08:45:07.60ID:C5b6ywPX
>>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
2022/06/08(水) 09:03:01.17ID:C5b6ywPX
あんまり頑固になっても聞かなさそうなんでそろそろ妥協案でも

どうしてもジェネリックでやりたかったら、num::PrimIntでも使ってればここまでの批判は無かったんじゃないですかね
BigUint/BigIntは範囲から外れるけど、それはやっぱりそういうものなんですよ
2022/06/08(水) 09:13:21.45ID:2tL4qRNc
>>546
あなたのコード>>539もclone()しているから
1回あたりclone()が1回発生している点で同じではないかね
そこは重要なところだから曖昧な推測で済ませずに細かい差異でベンチマークを取ったほうがいいのではないか
2022/06/08(水) 11:26:56.36ID:oyhrGaRU
Rustが自由自在に書けるようなプログラマになりたがったンゴねえ
ワイは低脳だから躓いてるンゴ
例えば&'static TとT: 'staticの違いがなんかあるらしいんやがわからなかったンゴ
前者はプログラム終了時まで生きる変数の参照って意味で後者はもしTに参照があったらそれは'static以上生きるって解釈であってるんか?
2022/06/08(水) 11:49:32.36ID:oyhrGaRU
いや理解したんご
前者は参照型しか受け付けないけど後者はそれ以上の種類の型を受け付けるンゴねえ
さらに違いがあるかもだけど勉強進めるわ
なんでもなかった
2022/06/08(水) 12:37:42.94ID:C5b6ywPX
>>548
そのベンチが>>539のつもりなんだけど、これにどういう問題があって具体的には何をしろと?
from_fn使ってる分(5)のほうが近いから比較対象を(1)から(5)に変えろってこと?

というかそれが分かっているなら他人にやらせるんでなく自分で検証すればいいのでは?
2022/06/08(水) 14:46:42.18ID:JNpA1ROM
>>551
結局、何が原因なん?
ジェネリック?それともchecked_add?あるいは変数Some?まさかのswap?
Rustスレとしてはコードよりも原因を知りたい
2022/06/08(水) 15:00:02.66ID:0R8j40RZ
>>502
「1.5倍も差があるのは妙だな Rustでは最適化されるのでジェネリックで書こうがそんな差は出ないはず」
これがそもそもおかしい、最適化されようが何だろうが生成されるコードは違うのでMIRなりdisamなりでインストラクション単位で目視すれば一発だろ。ベンチを取る以前の思い込み低レベルな話
そしてほぼ最適化された無駄のないコードだったとしても
>>523
ここ5年程度のCPUでは64バイトのDSB境界を持つ小さなループ呼び出しなどが単一のμopsキャッシュに収まる場合があるがコードの配置によって異なり1.5倍程度の差が出ても不思議じゃない。
言ってるのに全く聞かない
2022/06/08(水) 15:48:23.76ID:kiLfNcoT
>>553
その件は1.5倍差あった>>481がイテレータと関数を比較するという大チョンボをしていたことが原因と判明済
そしてジェネリックか否か自体では速度に差が出ないことを>>502のベンチが証明済
2022/06/08(水) 17:10:39.22ID:C5b6ywPX
>>554
よく見ろ、それは>>475の話だ
>>481は両方とも(usize) -> BigUintな関数
2022/06/08(水) 17:16:08.77ID:LlAtoLIj
これだけ時間をかけても原因すら分からずノンジェネリックとの速度差を埋められない状況をコストとして認識できてないのが恐ろしい
2022/06/08(水) 17:31:51.50ID:H0oyRmek
一般的に、数列を順に求めるイテレータと、
そのうちの特定の数だけを求める関数とでは、
オーダー問題もアルゴリズムも変わってくるため、
>>481はまた別の問題となっている。
イテレータ同士の比較で1.5倍となっていないことからも、
異なる問題であると理解できるはず。

>>556
ジェネリックとノンジェネリックに速度差が無いことは、
>>502で既に示されたのだから、
ジェネリックかどうかは一切関係ないと思う。
ジェネリックとは別の問題。
2022/06/08(水) 18:18:03.20ID:cKPONsWM
>>557
>>502はジェネリックでも実現できるコードをノンジェネリックにしただけ

ノンジェネリックならadd_assign, mem::swap, cloneで>>502のいずれよりも速いコードが書けるが
ジェネリックだとchecked_addを使わざるを得ず同じことが実現できない
2022/06/08(水) 18:32:47.55ID:y1p7Fxu2
>>537では「ジェネリックよりも速いコードがあるならきちんと示そうぜ」と言っていて
>>540の言う違いを理解している感じだったのに
いざ本当にコードが出てくるとジェネリクス自体のオーバーヘッドの話に限定して、差は無いと連呼

わざとやってんの?
2022/06/08(水) 19:11:11.80ID:sj9oTS9C
>>558
> ジェネリックだとchecked_addを使わざるを得ず同じことが実現できない

それは違うのではないか?
ジェネリックでも自由にCheckedAddAssign等を定義して実現することが可能という話が既に出ている >>492 >>543
一方でノンジェネリックで書いてもオーバフロー対策としてchecked_addは使わざるを得ない
つまりどちらが有利とか優れているとかいう問題ではない
2022/06/08(水) 19:45:52.60ID:btlg3B6B
>>560
他人の意見を鵜呑みにしてないでやってみれば?
俺はちょっと試してみたけど結局無理だと確信したよ
2022/06/08(水) 19:54:30.37ID:hF0KVPZD
CheckedAddAssignの定義難しいよね
cloneを減らせるうまい定義見せて欲しい
2022/06/08(水) 19:58:01.42ID:hF0KVPZD
>>560
> 一方でノンジェネリックで書いてもオーバフロー対策としてchecked_addは使わざるを得ない
つまりどちらが有利とか優れているとかいう問題ではない

BigUintの場合はオーバーフローを想定しなくて良いからただのAddAssignで良いよね
ジェネリックな実装の場合は考慮すべき事項が増えるというハンデを抱えている
2022/06/08(水) 20:09:35.76ID:Pauu0yN9
基地同士の喧嘩おもすれー
2022/06/08(水) 21:16:33.76ID:zfNTYu3X
ジェネリックでなくても各i8版~u128版でchecked_add要るんじゃね?
2022/06/08(水) 21:31:30.99ID:uKz/tAPi
>>560
CheckedAddAssignはAddAssignと同じようには実現できないよ
速度差は他の方法で工夫すれば埋めることは不可能ではない
2022/06/08(水) 22:52:52.99ID:C5b6ywPX
このままでは誰も気付かなさそうなのでここでネタばらし
>>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
2022/06/08(水) 23:10:54.19ID:Pauu0yN9
Rust使うやつは全員クズ
2022/06/08(水) 23:14:19.56ID:xZpQpCco
ゴミみてぇに使いにくい
2022/06/08(水) 23:33:46.23ID:1Qgkgfnu
>>567
ジェネリックは遅くて使い物にならずRustはクソ言語のいい流れが出来ていたのに邪魔すんなボケ
2022/06/09(木) 00:05:50.09ID:8AO4ag5u
>>567
それが本当にベンチマークしたかった内容なのかな?

Nの変化による性能差の変化が重要
Rcでイテレータ返すやつと合わせて確認すればN=50000だと差がなくなる理由も分かる
2022/06/09(木) 01:08:31.17ID:b8HehfnZ
>>567
裏切り者め
隠し通せよ
2022/06/09(木) 09:43:05.84ID:m8hzuB37
>>567
結局ジェネリックに書いても非ジェネリックでも速さはほぼ同じなのかよ
どんな方法で書いても結果を返すためにclone相当が最低1回は必要で
>>502のジェネリック版はclone相当がchecked_addでの1回のみだからこれ以上は速くできないってことか
2022/06/09(木) 11:12:09.28ID:5tn+SNbG
複オジ必死やなw
2022/06/09(木) 11:39:59.58ID:gQa8Lild
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()は必要ないのか
2022/06/09(木) 11:41:07.83ID:gQa8Lild
まちがえたこうだ

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();
2022/06/09(木) 11:52:52.81ID:WWB1ag70
>>573
IteratorのItem生成のためにcloneが必要という話なので
参照返すとかRc<RefCell>にするとかすればまだ改善する余地はありそうではある
2022/06/09(木) 14:32:02.03ID:BXa7hn4f
「Atom」の開発者が究極のコードエディターを目指す ~「Zed」の開発が始動
「Electron」を捨て、Rust言語を採用。GPUI、tree-sitterなどで武装し、超高速なコードエディターに
https://forest.watch.impress.co.jp/docs/serial/yajiuma/1374986.html
2022/06/09(木) 14:58:44.89ID:G7q6UoxI
「重要」でスレ内検索かけると……
2022/06/09(木) 16:58:07.35ID:/uOnDbzK
>>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できる
2022/06/09(木) 17:07:43.03ID:3qzGL8h6
>>577
Rc版はmake_mutにすれば呼び出し側が参照をつかんでる時だけcloneにフォールバックしてくれる
つかんでなければcloneしないので高速
全ての値をつかむようならRcを使わないやり方より少し遅くなる
2022/06/09(木) 20:30:30.68ID:sXhLSFat
>>355はRustだと末尾呼び出しの最適化が効くの?
末尾呼び出し最適化必須のschemeですら自動的には最適化されず、人間が意味を解析して、アキュムレーター使って末尾再帰になるようにしましょうって練習問題になるくらいなのに。
Rust凄い!!
2022/06/09(木) 21:24:26.48ID:xbJg8ij+
>>581
簡易的なstreaming iteratorにする方法もあるよ
2022/06/09(木) 22:43:27.67ID:k8dtcEck
>>582
どういう理解をしてるのかようわからんが、 >>355 はいわゆる末尾呼出しではないよ。
2022/06/10(金) 00:02:10.12ID:/2sYVq21
https://twitter.com/Ray__March/status/1523717266730151936
Crab Rave
https://twitter.com/5chan_nel (5ch newer account)
586582
垢版 |
2022/06/10(金) 12:26:19.22ID:xMTaqdcz
>>584
340くらいから末尾呼び出し最適化の話題があって、355の2で「リリースモードだとスタックが溢れない」と書いてあったので、末尾呼び出し最適化が効いたのかと思いました。
十分なスタック容量があっただけ?

1+count(n-1)

count(n-1, acc+1)
に書き換えてくれる最適化があるのかな、と思いまして
2022/06/10(金) 12:39:41.49ID:awrGQFqA
>>586
生成されたバイナリを見た方が良いよ
https://godbolt.org/z/Kcd6zf68e
定数たたみ込みでnopになってるっぽい
2022/06/10(金) 12:44:00.71ID:NmVzwec3
>>583
ストリーミングイテレータを試してみたけどRc使ったほうが少し速かった
ただ呼び出し側が参照をつかんだままにするとコンパイルエラーにしてくれるのでRcより望ましいケースが多々ありそう
2022/06/10(金) 13:14:03.27ID:/2sYVq21
streaming iterator! そういうのもあるのか
自分への参照を返せるんだね
使うかどうかは分からんけど覚えておこう
590582
垢版 |
2022/06/10(金) 17:55:03.36ID:k70t2J8V
>>587
すまん
2022/06/10(金) 20:18:18.95ID:din4Kjb/
>>586
すでに >>587 が指摘しているが、定数畳み込みが起こっている。 入力が定数で、かつそれに対する演算が副作用のない基本的なものであった場合に定数畳み込みがされやすい。 定数ではない場合でもこの関数 count は
mov rax, rdi
ret
になってて、入力をそのまま返す形にまで最適化されるので末尾呼出しがどうこうというレベルのものではなくなっている。

最適化というのは、レジスタ割り当てなどは理論的な背景がはっきりしているが、多くの細々としたものは「大量の置き換えパターンを辞書のように持っている」という物量で押し切る泥臭いものだったりするので (それをやりやすいようなデータ構造とかに工夫はあると思うが) 結局のところは投入されたリソースが多いやつが強い。

ちなみに Scheme の末尾呼出し最適化は言語仕様で要求する最低限度がそれだけ (しかし常にやらなければならない) という意味であって、それ以上の最適化をやっちゃ駄目という意味ではないよ。 最適化をどのレベルまでやるかは処理系次第。
2022/06/10(金) 20:27:25.22ID:VliTcE7P
こいつが出てくると結論が1つも分からなくなる
2022/06/10(金) 21:05:43.32ID:uz7MKgqc
複オジと同じ臭い
2022/06/10(金) 21:45:41.77ID:iyAWtrh4
汚文章は汚コードの兄弟
同じ親から生まれてくるもの
2022/06/10(金) 22:32:01.13ID:r0Sf5PMX
最適化の話はかなりコンパイラーに詳しくないとなぜそうなるかって分からないだろうからな
コンパイラーの最適化について話せる奴はプログラミング中級者以上だろ。
(本職プログラマなら話せないと知識なさすぎと言われるだろうが)
趣味でプの俺は永遠に初心者レベルでそんな知識ないから、こいつ何を言っているんだ?だが
2022/06/10(金) 22:32:11.19ID:+N1EN6wu
まぁ要するに

×××という最適化処理が処理系の規格として定められているのなら処理系の開発者(=コンパイラとか作る人)はその最適化を実現しないといけないしそれを利用するプログラマは処理系が”上手いことやってくれる”と期待していい、しかしそれが言語規格上は必須とされてない処理については処理系が“うまいことやつてくれる”と基本は期待してはいけない
けど、規格で求められてないような高度な最適化処理を“してはいけない”わけではない、最新の理論で見つかった最適化処理など取り入れる分には好きにして構わない

という意味でしょ
Haskellのメモ化処理とかでもよく出てくるよ
GHCって言うすごい処理系があってHaskellの標準規格では全然定められてないような最適化処理をバンバンやってくれるから“なんでこんなにはやいの?とりま作っただけなのに”と思うこと時々あるからな
2022/06/10(金) 22:36:04.99ID:3HE2W+m8
最適化と言えば&mutがnoaliasになって高速化したコード出会ったことある人居る?
2022/06/10(金) 22:56:48.93ID:/Qg1cUoJ
>>596
要するに~
元の説明より長なっとるやないかーいww
脳みそ整理整頓してこんかーいww
2022/06/10(金) 23:03:01.48ID:EifRM46R
>>595
初心者自演乙オジ
2022/06/10(金) 23:39:18.10ID:QxuEFd4p
またいつもと同じパターン
善人 = 情報や説明やコード等を書いてくれる人
悪人 = 文句や批判だけの人

>>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
2022/06/10(金) 23:52:37.74ID:q3uEdydr
仕様ころころゴミ言語
2022/06/10(金) 23:57:33.08ID:Vy8jfUtT
ソースこれですか
https://stackoverflow.com/a/57259339
2022/06/11(土) 00:21:37.71ID:nVHax23k
>>602
「rust add assign optimize site:stackoverflow.com」でトップヒットだったわw
どおりでね
2022/06/11(土) 00:47:00.69ID:41aFXNPT
>>601
Rustの仕様は変わっていない
LLVMへの最適化指示のうちの一つをLLVMのバグ発見のため一時的にオフとしていただけ
2022/06/11(土) 00:53:30.81ID:6T6IERuk
そんなつまんねーのに反応すんなよ……
2022/06/11(土) 01:51:51.23ID:coFBEVyx
マッチポンピング好きだねぇ
2022/06/11(土) 11:14:20.05ID:FpznSlgy
そろそろRust製の有名なソフトウェア作ってからビックマウスしてくださいね、Firefox以外で
2022/06/11(土) 11:39:14.69ID:fd4RDbWP
>>606
マッチポンプも過疎スレのにぎわい
2022/06/11(土) 11:54:00.75ID:sRR0HfwK
TechEmpower Round 18で1.5倍の差を付けて堂々の1位をかっさらったactixは有名ソフトウェアではない了解
2022/06/11(土) 15:51:26.10ID:Lxou0O6d
DiscordとかDropboxとか
2022/06/11(土) 16:19:59.18ID:C3/u0lQ5
WinとかLinuxの中身ですでに使われてなかった?
2022/06/11(土) 18:52:01.33ID:BGPUwt90
>>593
同じ臭いも何も同一人物だろ
2022/06/11(土) 19:26:39.50ID:WsHL0uxM
>>611
Linuxはまだ
winは確実なソースあったっけ?
OS系だとAndroidでは使われてる(まだデフォルトで有効ではないけど)
2022/06/11(土) 23:25:25.63ID:HlAQKNMT
なんでRound18なんて大昔の過去を?
2022/06/12(日) 06:12:09.52ID:6S+GFICB
>>612
どうでもいい

>>613
同じくどうでもいい
2022/06/12(日) 17:11:51.09ID:tUHADwRi
Rustはver2.0にはなりませんって言ってるけど実質はとっくの昔にver2.0になってる
2022/06/12(日) 19:14:45.66ID:geXDvND7
>>616
どういうこと?
2022/06/12(日) 20:36:02.36ID:nrxswUhC
>>562 >>566
CheckedAddAssignにこだわる必要はないため、発想を転換して、
checked_add()の原関数であるoverflowing_add()を用いることで、
overflowing_add_assign()を用意して同じようにbool値を返せば解決する

具体的には以下のように引数はadd_assign()と同じでbool値を返せばよい
trait OverflowingAddAssign {
 fn overflowing_add_assign(&mut self, rhs: &Self) -> bool;
}

オーバーフローするi8型〜u128型にはoverflowing_add()があるため実装はこうなる
 let is_overflow;
 (*self, is_overflow) = self.overflowing_add(*rhs);
 is_overflow
この3行のコードでちゃんと最適化されるかどうかを確認するため、
単純にadd_assignを用いた場合、すなわち「*self += rhs」と比較すると
https://godbolt.org/z/WP3En8xM8
のアセンブリ出力となり、オーバーフローを返す以外は同一に最適化されることが確認できる

一方でオーバーフローしないBigUintなどの型への実装はこうなる
 *self += rhs;
 false
つまりオーバーフローの結果として常にfalseを返すので、
こちらは使う側でオーバーフローの扱いが消えてadd_assign部分のみに最適化される

したがってこのOverflowingAddAssignを用いてジェネリックに書けば、
どちらの型の場合であっても、非ジェネリックに書いた時と同一コードとなる
■ このスレッドは過去ログ倉庫に格納されています
5ちゃんねるの広告が気に入らない場合は、こちらをクリックしてください。