公式
https://www.rust-lang.org/
https://blog.rust-lang.org/
https://github.com/rust-lang/rust
公式ドキュメント
https://www.rust-lang.org/learn
Web上の実行環境
https://play.rust-lang.org
※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/
※次スレは原則>>980が立てること
前スレ
Rust part25
https://mevius.5ch.net/test/read.cgi/tech/1722354386/
ワッチョイスレ
プログラミング言語 Rust 4【ワッチョイ】
https://mevius.5ch.net/test/read.cgi/tech/1514107621/
探検
Rust part26
レス数が950を超えています。1000を超えると書き込みができなくなります。
1デフォルトの名無しさん
2024/09/20(金) 22:18:38.38ID:c48cFuZJ882デフォルトの名無しさん
2024/11/18(月) 21:41:56.71ID:K2lQU8l5 実際にはunsafe使わないRustはCよりもいくらかオーバーヘッドが生じるとは思う
Cでなポインタのコピーで済むけどsafe RustだとArcが必要だからcloneの際にロックのコストがかかるとか、配列へのインデックスでのアクセスで境界チェックされるとか
Rustでは安全側に寄せる分のコストはかかるはず
Cでなポインタのコピーで済むけどsafe RustだとArcが必要だからcloneの際にロックのコストがかかるとか、配列へのインデックスでのアクセスで境界チェックされるとか
Rustでは安全側に寄せる分のコストはかかるはず
883デフォルトの名無しさん
2024/11/18(月) 21:52:16.61ID:k3+/8xDm >>882
本当に各チェックを安全に外せる場合
つまり安全なインターフェイスを提供できる場合
Rustでもそれを安全なライブラリとして提供すればよいですね
実際にそのようにしてRustの標準ライブラリが作られて来ていますから
本当に各チェックを安全に外せる場合
つまり安全なインターフェイスを提供できる場合
Rustでもそれを安全なライブラリとして提供すればよいですね
実際にそのようにしてRustの標準ライブラリが作られて来ていますから
884デフォルトの名無しさん
2024/11/18(月) 22:05:29.90ID:1mdid6am >>879のコード例だと本当はアウトなのに屁理屈でセーフという俺ルールでねじ曲げてるだけに見える
それunsafeやない、アウトや!
それunsafeやない、アウトや!
885デフォルトの名無しさん
2024/11/18(月) 22:35:51.22ID:SToHXvxk 計測して本当にunsafeにする価値がある部分だけ暴走覚悟でunsafeにすればいい
満たさないと危なくなる条件はdebug_assertしておくと気休めになる
満たさないと危なくなる条件はdebug_assertしておくと気休めになる
886デフォルトの名無しさん
2024/11/18(月) 22:46:47.54ID:r0p6egBs >いくらかオーバーヘッドが生じるとは思う
そんなレベルじゃないだろw
そんなレベルじゃないだろw
887デフォルトの名無しさん
2024/11/18(月) 22:49:05.04ID:7J3JrtFR >>882
安全のためのオーバーヘッドはどちらの言語も同じです
Rustも&TならばCopy実装型なのでコピー出来ますからC言語と同じです
Arcのcloneはロックフリーです
ロックされるのはその中で用いるMutexなど
C言語でも排他制御が必要なところではMutexが使われます
ヒープを使うデータをポインタで指す人数が変化していくならば最後の人が解放するためにリファレンスカウント管理が必要です
実際にC++ではそれがshared_ptrとしてArcと同様なものが提供されています
安全のためのオーバーヘッドはどちらの言語も同じです
Rustも&TならばCopy実装型なのでコピー出来ますからC言語と同じです
Arcのcloneはロックフリーです
ロックされるのはその中で用いるMutexなど
C言語でも排他制御が必要なところではMutexが使われます
ヒープを使うデータをポインタで指す人数が変化していくならば最後の人が解放するためにリファレンスカウント管理が必要です
実際にC++ではそれがshared_ptrとしてArcと同様なものが提供されています
888デフォルトの名無しさん
2024/11/18(月) 22:53:38.18ID:+RZAZC6X よかった、RustとCではオーバーヘッドは同じがRustの方が少ないんだね
889デフォルトの名無しさん
2024/11/18(月) 22:59:47.77ID:x8ZZBVl/ 前提条件大杉
890デフォルトの名無しさん
2024/11/18(月) 23:17:10.99ID:tFghvvKh >>888
複おじ、幼稚すぎw
複おじ、幼稚すぎw
891デフォルトの名無しさん
2024/11/18(月) 23:40:55.05ID:k3+/8xDm Rc相当がなくArc相当のshared_ptrしかないC++はオーバーヘッドが大きい
892デフォルトの名無しさん
2024/11/18(月) 23:52:07.17ID:dSfvQiDe C++でポインタいじってる時も特定の前提条件の時まともに動くだけで、そこから外れたらすぐバグるから。安全性のレベルを合わせたら結局どちらも同じようなコードになるよ。条件チェックしてるのとしてないのを比較して速い遅い言われても。
あと、rustの方が型で前提条件弾いて全域関数を作りやすいから。下手なC++よりは最適化される場合もある。何にせよ最初ほ安全に振っておいて、そこからプロファイラかけて遅いところだけ変えて行くほうがいいと思うけどね。
あと、rustの方が型で前提条件弾いて全域関数を作りやすいから。下手なC++よりは最適化される場合もある。何にせよ最初ほ安全に振っておいて、そこからプロファイラかけて遅いところだけ変えて行くほうがいいと思うけどね。
893デフォルトの名無しさん
2024/11/19(火) 00:32:35.22ID:GSnhfwF9 参考までに聞きたいんだけど、画像処理みたいなタスクってunsafe無しでもC/C++と同等の速度を出せるの?
フィルタのように周辺画素の値を使う処理や、処理対象の画素 (もしく行) を複数スレッドに分割するような処理を想定してる
自分の知識だと、可変かつマルチスレッドのような場合はsafe Rustだと難しい気がしてる
unsafeを使うなら、オーバーラップしないように範囲を分割して、そのポインタを渡して処理させることはできるけど、safe Rustだと可変借用のルールが問題になる気がしてる
それこそunsafeを使うべき場面だというなら納得するし、safe Rustでもうまくやれるなら知っておきたい
フィルタのように周辺画素の値を使う処理や、処理対象の画素 (もしく行) を複数スレッドに分割するような処理を想定してる
自分の知識だと、可変かつマルチスレッドのような場合はsafe Rustだと難しい気がしてる
unsafeを使うなら、オーバーラップしないように範囲を分割して、そのポインタを渡して処理させることはできるけど、safe Rustだと可変借用のルールが問題になる気がしてる
それこそunsafeを使うべき場面だというなら納得するし、safe Rustでもうまくやれるなら知っておきたい
894デフォルトの名無しさん
2024/11/19(火) 00:50:32.75ID:FW/CGHup >>893
rayon crateというデーター並列処理のライブラリを使う。チャンクに分割されたパラレルイテレータを回すだけ。フィルター処理とかは割と簡単。
rayon crateというデーター並列処理のライブラリを使う。チャンクに分割されたパラレルイテレータを回すだけ。フィルター処理とかは割と簡単。
895デフォルトの名無しさん
2024/11/19(火) 01:54:46.13ID:FW/CGHup use image::{ImageBuffer, Rgb, RgbImage};
use rayon::prelude::*;
fn to_grayscale(img: &RgbImage) -> RgbImage {
let (width, height) = img.dimensions();
let mut output = ImageBuffer::new(width, height);
output.par_chunks_mut(3).zip(img.par_chunks(3)).for_each(|(out, pixel)| {
// RGB to グレースケール変換の重み付け
let gray = (0.299 * pixel[0] as f32 +
0.587 * pixel[1] as f32 +
0.114 * pixel[2] as f32) as u8;
out[0] = gray;
out[1] = gray;
out[2] = gray;
});
output
}
fn main() -> Result<(), image::ImageError> {
let img = image::open("input.jpg")?.to_rgb8();
let gray_img = to_grayscale(&img);
gray_img.save("output.jpg")?;
Ok(())
}
use rayon::prelude::*;
fn to_grayscale(img: &RgbImage) -> RgbImage {
let (width, height) = img.dimensions();
let mut output = ImageBuffer::new(width, height);
output.par_chunks_mut(3).zip(img.par_chunks(3)).for_each(|(out, pixel)| {
// RGB to グレースケール変換の重み付け
let gray = (0.299 * pixel[0] as f32 +
0.587 * pixel[1] as f32 +
0.114 * pixel[2] as f32) as u8;
out[0] = gray;
out[1] = gray;
out[2] = gray;
});
output
}
fn main() -> Result<(), image::ImageError> {
let img = image::open("input.jpg")?.to_rgb8();
let gray_img = to_grayscale(&img);
gray_img.save("output.jpg")?;
Ok(())
}
896デフォルトの名無しさん
2024/11/19(火) 02:09:20.81ID:FW/CGHup サンプル書いてみた。
RGB画像をグレースケールに変換する。
imgが入力画像、outputが出力画像のバッファ。
イテレータで回してクロージャー呼んでる。
per_chunks_mut、per_chanksでチャンクのサイズ指定。今は1ピクセルrgbで3バイトずつ取り出してクロージャーの引数として渡される。スレッドの並列処理は自動で行われてる。
例えばチャンクサイズをwidth×3とかにすれば1ラインずつデータが渡される。width×3×2とかにすれば2ラインずつ。ある程度のサイズにしたほうが高速になる。
チャンクのサイズを変えたらクロージャーの処理も変えるのを忘れずに。
RGB画像をグレースケールに変換する。
imgが入力画像、outputが出力画像のバッファ。
イテレータで回してクロージャー呼んでる。
per_chunks_mut、per_chanksでチャンクのサイズ指定。今は1ピクセルrgbで3バイトずつ取り出してクロージャーの引数として渡される。スレッドの並列処理は自動で行われてる。
例えばチャンクサイズをwidth×3とかにすれば1ラインずつデータが渡される。width×3×2とかにすれば2ラインずつ。ある程度のサイズにしたほうが高速になる。
チャンクのサイズを変えたらクロージャーの処理も変えるのを忘れずに。
897デフォルトの名無しさん
2024/11/19(火) 02:14:25.94ID:FW/CGHup これをC++で書けと言われたらやりたくない。
rustなら安全で分かりやすく書けるし、イテレータは並列処理の最適化が効く。
rustなら安全で分かりやすく書けるし、イテレータは並列処理の最適化が効く。
898デフォルトの名無しさん
2024/11/19(火) 07:54:11.15ID:126iZ9C9 rayonが出たついでの質問なんだけど、rayonのイテレーター (par_iterなど) ってグローバルなスレッドプールでなく、ThreadPoolBuilder::build で作ったスレッドプール上で実行できる?
以前調べた際によく分からなかった
以前調べた際によく分からなかった
899デフォルトの名無しさん
2024/11/19(火) 08:24:41.51ID:0JKwCmNc ところでこのスレって業務で実際にrust使ってるよーって人います?
900デフォルトの名無しさん
2024/11/19(火) 08:27:40.98ID:FW/CGHup スレッド数を自分で設定したいって意味でいいのかな?
rayon::ThreadPoolBuilder::new().num_threads(8).build_global().unwrap();
rayon::ThreadPoolBuilder::new().num_threads(8).build_global().unwrap();
901デフォルトの名無しさん
2024/11/19(火) 08:32:14.22ID:FW/CGHup use rayon::ThreadPoolBuilder;
// カスタムスレッドプール作成
let pool = ThreadPoolBuilder::new()
.num_threads(4) // スレッド数指定
.build()
.unwrap();
// スレッドプールで特定の処理を実行
pool.install(|| {
output.par_chunks_mut(row_size)
.zip(img.par_chunks(row_size))
.for_each(|...| {
// 処理
});
});
// カスタムスレッドプール作成
let pool = ThreadPoolBuilder::new()
.num_threads(4) // スレッド数指定
.build()
.unwrap();
// スレッドプールで特定の処理を実行
pool.install(|| {
output.par_chunks_mut(row_size)
.zip(img.par_chunks(row_size))
.for_each(|...| {
// 処理
});
});
902デフォルトの名無しさん
2024/11/19(火) 14:47:04.76ID:9IiXc5Vb903デフォルトの名無しさん
2024/11/19(火) 15:24:29.64ID:+UtMc6V6904デフォルトの名無しさん
2024/11/19(火) 15:42:39.43ID:s9mRA7mb Rustが勝利した原因はrayonやtokioなどのマルチスレッドを便利に安全に活かすライブラリの存在が大きいが
C/C++は数十年の年月を重ねてもそれに匹敵するものが完成しなかった
C/C++は数十年の年月を重ねてもそれに匹敵するものが完成しなかった
905デフォルトの名無しさん
2024/11/19(火) 16:37:47.00ID:Yysxm38B >>903
発端はrustでc++みたいなフィルター処理書ける?って話。c++でも書けるかもしれんが自分は面倒なんで誰かコード書いてくれ。
発端はrustでc++みたいなフィルター処理書ける?って話。c++でも書けるかもしれんが自分は面倒なんで誰かコード書いてくれ。
906デフォルトの名無しさん
2024/11/19(火) 22:42:01.95ID:126iZ9C9 >>901
ありがたい
やりたいのは「明示的に指定した場合のみ並列処理をする」プログラムで、データとしては Option::ThreadPool みたいなものを持ってるから、その中で実行したいという話
よく分かってなかったのは install の動作で、これに渡したクロージャーはプール内のスレッドで実行されると思ってたから、例えば4スレッドの場合に「スレッド1がpar_chunksを含むコードを呼びだす、それを受けてスレッド2-4が並列実行する (スレッド1はinstallに渡したクロージャの終わりでブロックされる) 」みたいなことになったりしないか…って思ってた
(公式のリファレンスは Executes op within the threadpool. という説明)
問題なさそうなら使わせてもらいます
ありがたい
やりたいのは「明示的に指定した場合のみ並列処理をする」プログラムで、データとしては Option::ThreadPool みたいなものを持ってるから、その中で実行したいという話
よく分かってなかったのは install の動作で、これに渡したクロージャーはプール内のスレッドで実行されると思ってたから、例えば4スレッドの場合に「スレッド1がpar_chunksを含むコードを呼びだす、それを受けてスレッド2-4が並列実行する (スレッド1はinstallに渡したクロージャの終わりでブロックされる) 」みたいなことになったりしないか…って思ってた
(公式のリファレンスは Executes op within the threadpool. という説明)
問題なさそうなら使わせてもらいます
907デフォルトの名無しさん
2024/11/19(火) 22:46:22.71ID:jmJ5BpPK C++で並列とかようやらんわ
SendもSyncもないとかもう考えられん
SendもSyncもないとかもう考えられん
908デフォルトの名無しさん
2024/11/19(火) 22:49:56.47ID:126iZ9C9 違うかも?
>>906 のスレッド4つの例だと、クロージャー自体はプール内のスレッド(スレッド1とする) で実行されて、スレッド1はpar_iterで並列処理を開始した後すぐ抜けて par_iter の仕事に加わるということ?
>>906 のスレッド4つの例だと、クロージャー自体はプール内のスレッド(スレッド1とする) で実行されて、スレッド1はpar_iterで並列処理を開始した後すぐ抜けて par_iter の仕事に加わるということ?
909デフォルトの名無しさん
2024/11/20(水) 00:33:04.50ID:shrZYon3 例えばスレッドプールを4で設定するとワーカースレッドが4つになります。でそれとは別にメインスレッドがあるわけで、このパラレルの処理をするときはメインスレッドもワーカーとして参加します。なので5個で回る感じ。
910デフォルトの名無しさん
2024/11/20(水) 00:36:52.89ID:ijtcomF1 pool.installとpool.scopeでメインスレッドがワーカーとして参加するかしないかが変わるみたい。
911デフォルトの名無しさん
2024/11/20(水) 00:42:34.33ID:e0+ziHsU >>907
C++にasyncがあるぞ。
C++にasyncがあるぞ。
912デフォルトの名無しさん
2024/11/20(水) 00:47:56.81ID:ijtcomF1 いずれにせよパラレルイテレータを回しているときは処理が終わるまで待つことになるんで、メインスレッド止めたくないときは別スレッドで立てる感じ。
fn non_blocking_example() {
let (tx, rx) = mpsc::channel();
std::thread::spawn(move || {
let pool = ThreadPoolBuilder::new()
.num_threads(4)
.build()
.unwrap();
pool.install(|| {
// 並列処理
});
tx.send("Done").unwrap();
});
// メインスレッドは他の処理を継続可能
println!("Doing other work");
// 必要なタイミングで結果を受信
match rx.recv() {
Ok(msg) => println!("Processing complete: {}", msg),
Err(e) => println!("Error: {}", e),
}
}
fn non_blocking_example() {
let (tx, rx) = mpsc::channel();
std::thread::spawn(move || {
let pool = ThreadPoolBuilder::new()
.num_threads(4)
.build()
.unwrap();
pool.install(|| {
// 並列処理
});
tx.send("Done").unwrap();
});
// メインスレッドは他の処理を継続可能
println!("Doing other work");
// 必要なタイミングで結果を受信
match rx.recv() {
Ok(msg) => println!("Processing complete: {}", msg),
Err(e) => println!("Error: {}", e),
}
}
913デフォルトの名無しさん
2024/11/20(水) 01:09:41.69ID:ijtcomF1 >>911
asyncは全然別の話。
rustでは型に対してsendやsyncといった属性を付けるようなイメージ。sendが付いてなければ別スレッドにデータ渡せないとかsyncが付いてなければ同時に使えないとか、そういうスレッド対応してないものを使うとコンパイラに怒られる仕組みになってる。
asyncは全然別の話。
rustでは型に対してsendやsyncといった属性を付けるようなイメージ。sendが付いてなければ別スレッドにデータ渡せないとかsyncが付いてなければ同時に使えないとか、そういうスレッド対応してないものを使うとコンパイラに怒られる仕組みになってる。
914デフォルトの名無しさん
2024/11/20(水) 08:50:31.70ID:yTy4Ahlp915デフォルトの名無しさん
2024/11/20(水) 09:59:28.14ID:MYLVUJ4i 最近のCPUは速過ぎるから第三者から見れば「速さ」は見えない
バグなら見える
それで無人の機械で速さを計測するから
第三者などという人間は不要だと分かる
バグなら見える
それで無人の機械で速さを計測するから
第三者などという人間は不要だと分かる
916デフォルトの名無しさん
2024/11/20(水) 11:26:15.05ID:W8mVvsIh Cが早くてRustが劣っていると仮定して
その差が問題なることなんてない
自分では何も生み出せないベンチ回マニアくらいだろ
その差が問題なることなんてない
自分では何も生み出せないベンチ回マニアくらいだろ
917デフォルトの名無しさん
2024/11/20(水) 12:43:18.25ID:/wT43F1g >>914
フィルター系のプログラムだとCPUのSIMD命令がかなり効くと思うんでそちらも検討するといいかと。
コンパイラが自動でやってくれる可能性もあるけど、明示的に書くと確実。
標準だと std::simd がそのうち実装される予定。
その他クレートもあるんで探してみて。
フィルター系のプログラムだとCPUのSIMD命令がかなり効くと思うんでそちらも検討するといいかと。
コンパイラが自動でやってくれる可能性もあるけど、明示的に書くと確実。
標準だと std::simd がそのうち実装される予定。
その他クレートもあるんで探してみて。
918デフォルトの名無しさん
2024/11/20(水) 13:08:23.05ID:LXAOodJ8 一般的なサイズの画像の全ピクセルをO(N)で舐める程度ならシングルスレッドで十分じゃね?まあSIMDはアリだが
ガチで速度出したいのって多数のファイルをバッチ処理するようなケースが多いから、
そういうときは結局ファイル単位で並列処理した方がスループット高かったりするんだよね
タスク内の並列化の方が技術的にはチャレンジングだからやりたくなる感情は理解するけどね
ガチで速度出したいのって多数のファイルをバッチ処理するようなケースが多いから、
そういうときは結局ファイル単位で並列処理した方がスループット高かったりするんだよね
タスク内の並列化の方が技術的にはチャレンジングだからやりたくなる感情は理解するけどね
919デフォルトの名無しさん
2024/11/20(水) 14:17:41.03ID:nL8S8oi5 >>879
馬鹿。
馬鹿。
920デフォルトの名無しさん
2024/11/20(水) 14:56:07.23ID:ytG52ull >>918
横からだが、画像フィルタは単なるわかりやすい例として出てるだけだろうから画像サイズなどは関係ない
一般的に多量のメモリ上でのある程度の計算処理が必要で、それがエリア分けして並列可能なら、並列化の検討余地が出てくる
ファイル処理などの件はIOバウンド特にリモートだとIO待ちが顕著になり別の対策が必要になってくる
一番極端な場合はtokioを使って並行並列化が最も速くなりうる
つまり1件に対して1スレッドではなく、1件に対して1タスク(async軽量タスク)を割り当て、1スレッドで複数のタスクが同時に並行に動く形になる
rayonのケースでもtokioのケースでも、利用する並列スレッド数は物理コアスレッド数を上限とする形
横からだが、画像フィルタは単なるわかりやすい例として出てるだけだろうから画像サイズなどは関係ない
一般的に多量のメモリ上でのある程度の計算処理が必要で、それがエリア分けして並列可能なら、並列化の検討余地が出てくる
ファイル処理などの件はIOバウンド特にリモートだとIO待ちが顕著になり別の対策が必要になってくる
一番極端な場合はtokioを使って並行並列化が最も速くなりうる
つまり1件に対して1スレッドではなく、1件に対して1タスク(async軽量タスク)を割り当て、1スレッドで複数のタスクが同時に並行に動く形になる
rayonのケースでもtokioのケースでも、利用する並列スレッド数は物理コアスレッド数を上限とする形
921デフォルトの名無しさん
2024/11/20(水) 21:20:24.03ID:LXAOodJ8 >>920
高説ごもっともだけど、多数のファイルのバッチ処理をするときには分割しないで1スレッドの方がスループットが高い説自体は間違ってはいないでしょ
SIMD含めスレッド内での最適化は尽くしていて単一プロセッサを100%使い切っているのであれば、
マルチスレッドに伴う諸々のオーバーヘッドやアルゴリズムの複雑化を避けられるから自明
もちろんシングルスレッドだとプロセッサ数に対して件数が十分に多くなきゃスループット落ちるしレスポンスも当然劣るから、一般にどちらが良いということではないが
高説ごもっともだけど、多数のファイルのバッチ処理をするときには分割しないで1スレッドの方がスループットが高い説自体は間違ってはいないでしょ
SIMD含めスレッド内での最適化は尽くしていて単一プロセッサを100%使い切っているのであれば、
マルチスレッドに伴う諸々のオーバーヘッドやアルゴリズムの複雑化を避けられるから自明
もちろんシングルスレッドだとプロセッサ数に対して件数が十分に多くなきゃスループット落ちるしレスポンスも当然劣るから、一般にどちらが良いということではないが
922デフォルトの名無しさん
2024/11/20(水) 21:35:21.34ID:5+HdYMGb923デフォルトの名無しさん
2024/11/20(水) 21:38:51.35ID:5+HdYMGb >>921
>>マルチスレッドに伴う諸々のオーバーヘッドやアルゴリズムの複雑化を避けられる
ここもおかしい
対象件数があればマルチスレッド起動のオーバーヘッドは誤差
各々に対するアルゴリズムは変わらない
>>マルチスレッドに伴う諸々のオーバーヘッドやアルゴリズムの複雑化を避けられる
ここもおかしい
対象件数があればマルチスレッド起動のオーバーヘッドは誤差
各々に対するアルゴリズムは変わらない
924デフォルトの名無しさん
2024/11/20(水) 21:52:13.97ID:jFXLNFvp パフォーマンスチューニングは実際の条件によるからね
4Kや8Kの画像に対して重ための非線形フィルタをかける場合ならマルチスレッド化の恩恵はあるだろう (より高速化するならGPU)
多量の画像をバッチ的に処理したいケースもあれば、カメラ画像のように、入力は常に最新の1枚だけという場合もある
それはそれとして、タスクの種類を問わない一般的な話として、Rustにおける (CPUバウンドな) 並列処理についての話が出たと思えば有益な情報だと思う
4Kや8Kの画像に対して重ための非線形フィルタをかける場合ならマルチスレッド化の恩恵はあるだろう (より高速化するならGPU)
多量の画像をバッチ的に処理したいケースもあれば、カメラ画像のように、入力は常に最新の1枚だけという場合もある
それはそれとして、タスクの種類を問わない一般的な話として、Rustにおける (CPUバウンドな) 並列処理についての話が出たと思えば有益な情報だと思う
925デフォルトの名無しさん
2024/11/20(水) 22:00:47.56ID:V/GV/ca9 >>923
スレッド起動以外にもマルチスレッドのオーバーヘッドはあるし、マルチスレッド化できるけど効率が悪化する画像処理アルゴリズムなんていくらでもある
それを誤差レベルとして無視できるかどうかはタスクや状況次第だが、いずれにせよゼロではない
スレッド起動以外にもマルチスレッドのオーバーヘッドはあるし、マルチスレッド化できるけど効率が悪化する画像処理アルゴリズムなんていくらでもある
それを誤差レベルとして無視できるかどうかはタスクや状況次第だが、いずれにせよゼロではない
926デフォルトの名無しさん
2024/11/20(水) 22:03:31.92ID:ytG52ull >>921
前提と何をするかによって変わりうるかな
例えばちょっと見方を変えるとそれと同種の、多数の人たちから色んなリクエストが来て処理して返す場合、つまりHTTPなどの各種サーバー類の場合
tokioを使ったマルチタスク・マルチスレッドが最も効率がよい
1つのCPUで最も多くの人数を同事に捌くことができる方法になると実証されている
前提と何をするかによって変わりうるかな
例えばちょっと見方を変えるとそれと同種の、多数の人たちから色んなリクエストが来て処理して返す場合、つまりHTTPなどの各種サーバー類の場合
tokioを使ったマルチタスク・マルチスレッドが最も効率がよい
1つのCPUで最も多くの人数を同事に捌くことができる方法になると実証されている
927デフォルトの名無しさん
2024/11/20(水) 23:45:54.40ID:5+HdYMGb >>925
複数の対象があると最初に言ってるのだから
個々の処理がマルチスレッドに不向きなアルゴリズムであっても
複数の対象を並列化すればよい
なぜアルゴリズムが複雑化すると思うのか?
アルゴリズムはそのままでいい
既出のrayonのコード例でも同じ処理(アルゴリズム)が並列に動くだけでありアルゴリズム部分に手を入れずに並列化できている
複数の対象があると最初に言ってるのだから
個々の処理がマルチスレッドに不向きなアルゴリズムであっても
複数の対象を並列化すればよい
なぜアルゴリズムが複雑化すると思うのか?
アルゴリズムはそのままでいい
既出のrayonのコード例でも同じ処理(アルゴリズム)が並列に動くだけでありアルゴリズム部分に手を入れずに並列化できている
928デフォルトの名無しさん
2024/11/21(木) 00:43:39.12ID:7teRxqa+ コードのサンプルはもっと複雑なのも考えたけど、ここじゃ載せきれないからシンプルにしたよ。この程度ならシングルスレッドでもすぐ終わるのはたしか。
でも複雑な画像処理ならCPUキャッシュのヒット率の方が処理速度に影響するんでキャッシュ溢れないように1つの画像をマルチスレッドで処理した方が速いかもしれない。
非同期が効くのはI/Oメインの処理の場合。何事も用途によりけりだよ。
でも複雑な画像処理ならCPUキャッシュのヒット率の方が処理速度に影響するんでキャッシュ溢れないように1つの画像をマルチスレッドで処理した方が速いかもしれない。
非同期が効くのはI/Oメインの処理の場合。何事も用途によりけりだよ。
929デフォルトの名無しさん
2024/11/21(木) 00:47:13.55ID:iDAcMnOY DllMainの引数を確認するべきじゃね?
スレッド起動毎に呼ばれるんだからオーバーヘッドが誤差は言い過ぎ
スレッド起動毎に呼ばれるんだからオーバーヘッドが誤差は言い過ぎ
930デフォルトの名無しさん
2024/11/21(木) 01:16:58.88ID:7teRxqa+ ここで言いたかった事は所有権や借用やunsafeの取り扱いで困るのはforループで書こうとした場合で、rustはイテレータ中心で考えると解放される場合が多いという事。配列だけでなくツリー構造でも。
なのでもっとイテレータ使いましょう。
なのでもっとイテレータ使いましょう。
931デフォルトの名無しさん
2024/11/21(木) 23:03:30.15ID:OGNNDR4U V8とRustをベースとしたJavaScript/TypeScriptランタイム環境「Deno」v2.1.0 ほか
https://forest.watch.impress.co.jp/docs/digest/1641518.html
https://forest.watch.impress.co.jp/docs/digest/1641518.html
932デフォルトの名無しさん
2024/11/22(金) 06:49:29.53ID:VaeItC08 >>931
Rustで作ると遅いんだよな
Rustで作ると遅いんだよな
933デフォルトの名無しさん
2024/11/22(金) 10:51:02.29ID:vbb23urH The Rust Programming Language:
Enums and Pattern Matching
Data Science Learning Community Videos
Enums and Pattern Matching
Data Science Learning Community Videos
934デフォルトの名無しさん
2024/11/22(金) 16:45:26.57ID:ssbKhBDs >>870
デバッグ *機能* とデバッグ(作業)の可否は別だろ
デバッグ *機能* とデバッグ(作業)の可否は別だろ
935デフォルトの名無しさん
2024/11/22(金) 16:52:08.57ID:ssbKhBDs >>882
Rustでロック必要なケースはC言語でだって必要だろ。
C言語の場合は手動で明示的にしてやる必要がある。
必要なチェックや排他制御のコード入れないでコンパイル通っただけで安心するやつは仕事でコード書かないでくれ。
チェックや排他制御が不要と言えるなら、それこそunsafeにすればいいじゃん。
Rustでロック必要なケースはC言語でだって必要だろ。
C言語の場合は手動で明示的にしてやる必要がある。
必要なチェックや排他制御のコード入れないでコンパイル通っただけで安心するやつは仕事でコード書かないでくれ。
チェックや排他制御が不要と言えるなら、それこそunsafeにすればいいじゃん。
936デフォルトの名無しさん
2024/11/22(金) 18:39:10.11ID:y0TICFrd そのキーワードをunsafeではなく「ハイリスクハイリターン」にでも
変えれば生霊が成仏するような気がする
リスクを100倍にすればリターンも100倍になるってのはただの物語にすぎないと個人的に思うが
科学だと思ってる人間がいても別に驚かない
変えれば生霊が成仏するような気がする
リスクを100倍にすればリターンも100倍になるってのはただの物語にすぎないと個人的に思うが
科学だと思ってる人間がいても別に驚かない
937デフォルトの名無しさん
2024/11/22(金) 18:50:58.98ID:MEPFF+NK >>882
C/C++/Rustのオーバーヘッドは同じ
メモリ管理もポインタで別主体の複数箇所から指すならC++のshared_ptrやRustのRc/ArcのようにCでも参照カウンタを持つしか安全に解放できない
C/C++/Rustのオーバーヘッドは同じ
メモリ管理もポインタで別主体の複数箇所から指すならC++のshared_ptrやRustのRc/ArcのようにCでも参照カウンタを持つしか安全に解放できない
938デフォルトの名無しさん
2024/11/22(金) 22:18:31.82ID:TcJB6S+5939デフォルトの名無しさん
2024/11/22(金) 22:39:33.83ID:y0TICFrd a 形式だけで安全といえる
b 中身をよく見れば安全といえる
c 形式も中身も危険
unsafeの部分はbとcが混ざっている
(bの価値がaより高いとは言ってないし安いとも言ってない)
b 中身をよく見れば安全といえる
c 形式も中身も危険
unsafeの部分はbとcが混ざっている
(bの価値がaより高いとは言ってないし安いとも言ってない)
940デフォルトの名無しさん
2024/11/23(土) 06:30:53.82ID:phMWL2Cw >>938
Rustでもロックは不要
例えばバッファをエリア8分割して8つのスレッドで書き換え並列処理
use rayon::prelude::*;
const BUF_SIZE: usize = 1 << 16;
const NUM_OF_AREA: usize = 8;
const AREA_SIZE: usize = BUF_SIZE / NUM_OF_AREA;
fn main() {
let mut buf: Box<[i64]> = (0..BUF_SIZE as i64).collect();
buf.par_chunks_mut(AREA_SIZE).for_each(|area| {
println!("DEBUG: {:?}", std::thread::current().id());
area.iter_mut().for_each(|n| {
*n = *n * *n;
});
});
}
Rustでもロックは不要
例えばバッファをエリア8分割して8つのスレッドで書き換え並列処理
use rayon::prelude::*;
const BUF_SIZE: usize = 1 << 16;
const NUM_OF_AREA: usize = 8;
const AREA_SIZE: usize = BUF_SIZE / NUM_OF_AREA;
fn main() {
let mut buf: Box<[i64]> = (0..BUF_SIZE as i64).collect();
buf.par_chunks_mut(AREA_SIZE).for_each(|area| {
println!("DEBUG: {:?}", std::thread::current().id());
area.iter_mut().for_each(|n| {
*n = *n * *n;
});
});
}
941デフォルトの名無しさん
2024/11/23(土) 10:31:17.67ID:ljLqVKjZ 外部クレートな上にイテレーターにしか使えないものでしょ
例えばこんな構造体
struct {
a: Vec<u8>,
b: Vec<u32>,
}
に対してスレッド1と2がそれぞれaとbを操作する場合は?とか、メモリ的に連続しないものを扱う場合は?とか、回避できないものはある
(後者は例えば、4動画を並列に処理し、それを上下左右に並べた1つの動画にする場合)
元のレスの「Rustでロックが必要なケースはC言語でも必要」という主張は必ずしもそうでない
(総合的には事故を防げるメリットの方が大きいし、「必要な場合のみunsafeを使う」というRustの方が良いと思ってるので、言語に対する批判ではないと思って欲しい)
例えばこんな構造体
struct {
a: Vec<u8>,
b: Vec<u32>,
}
に対してスレッド1と2がそれぞれaとbを操作する場合は?とか、メモリ的に連続しないものを扱う場合は?とか、回避できないものはある
(後者は例えば、4動画を並列に処理し、それを上下左右に並べた1つの動画にする場合)
元のレスの「Rustでロックが必要なケースはC言語でも必要」という主張は必ずしもそうでない
(総合的には事故を防げるメリットの方が大きいし、「必要な場合のみunsafeを使う」というRustの方が良いと思ってるので、言語に対する批判ではないと思って欲しい)
942デフォルトの名無しさん
2024/11/23(土) 11:04:40.44ID:AT4bo2Ti RustでもCでもロックが不要な例を出してはいけない
また「Cでは不要」の部分だけを自分で検証して残りは他責にするのは
近似としては悪くないが厳密には悪い
また「Cでは不要」の部分だけを自分で検証して残りは他責にするのは
近似としては悪くないが厳密には悪い
943デフォルトの名無しさん
2024/11/23(土) 14:25:42.64ID:ZNzlTdzo struct Test {
a: UnsafeCell<Vec<i32>>,
b: UnsafeCell<Vec<i32>>
}
// 手動でスレッドセーフであることを宣言
unsafe impl Sync for Test {}
impl Test {
fn new() -> Self {
Test {
a: UnsafeCell::new(Vec::new()),
b: UnsafeCell::new(Vec::new())
}
}
fn get_a(&self) -> &mut Vec<i32> {
unsafe { &mut *self.a.get() }
}
fn get_b(&self) -> &mut Vec<i32> {
unsafe { &mut *self.b.get() }
}
}
a: UnsafeCell<Vec<i32>>,
b: UnsafeCell<Vec<i32>>
}
// 手動でスレッドセーフであることを宣言
unsafe impl Sync for Test {}
impl Test {
fn new() -> Self {
Test {
a: UnsafeCell::new(Vec::new()),
b: UnsafeCell::new(Vec::new())
}
}
fn get_a(&self) -> &mut Vec<i32> {
unsafe { &mut *self.a.get() }
}
fn get_b(&self) -> &mut Vec<i32> {
unsafe { &mut *self.b.get() }
}
}
944デフォルトの名無しさん
2024/11/23(土) 14:28:48.33ID:ZNzlTdzo 使う側はこんな感じ。
fn main() {
let test = Test::new();
// 2つのスレッドで別々のフィールドにアクセス
std::thread::scope(|scope| {
scope.spawn(|| {
let a = test.get_a();
a.push(1);
});
scope.spawn(|| {
let b = test.get_b();
b.push(2);
});
});
}
fn main() {
let test = Test::new();
// 2つのスレッドで別々のフィールドにアクセス
std::thread::scope(|scope| {
scope.spawn(|| {
let a = test.get_a();
a.push(1);
});
scope.spawn(|| {
let b = test.get_b();
b.push(2);
});
});
}
945デフォルトの名無しさん
2024/11/23(土) 14:37:46.12ID:ZNzlTdzo c++はunsafeの部分を区別せずにやっちゃってるだけで、危険性があるのは変わらんのよ。rustの場合そこが明示的になってる分分かり易いというだけ。
946デフォルトの名無しさん
2024/11/23(土) 17:18:14.36ID:iTmIV0ch >>943
これsafeにしたらダメでしょ
これsafeにしたらダメでしょ
947デフォルトの名無しさん
2024/11/23(土) 17:57:14.51ID:AT4bo2Ti その石ころはパンに変化しなかった
はい論破
人は論破のために生きる
はい論破
人は論破のために生きる
948デフォルトの名無しさん
2024/11/23(土) 18:44:09.87ID:phMWL2Cw >>941
それならrayonを使うまでもないけど
使えばシンプルにこう書ける
struct Foo {
a: Vec<u8>,
b: Vec<u32>,
}
fn main() {
let mut foo = Foo {
a: vec![1, 2, 3],
b: vec![11, 22, 33],
};
rayon::join(
|| {
println!("DEBUG: a: {:?}", std::thread::current().id());
foo.a.push(4);
},
|| {
println!("DEBUG: b: {:?}", std::thread::current().id());
foo.b.push(44);
},
);
assert_eq!(foo.a, [1, 2, 3, 4]);
assert_eq!(foo.b, [11, 22, 33, 44]);
}
それならrayonを使うまでもないけど
使えばシンプルにこう書ける
struct Foo {
a: Vec<u8>,
b: Vec<u32>,
}
fn main() {
let mut foo = Foo {
a: vec![1, 2, 3],
b: vec![11, 22, 33],
};
rayon::join(
|| {
println!("DEBUG: a: {:?}", std::thread::current().id());
foo.a.push(4);
},
|| {
println!("DEBUG: b: {:?}", std::thread::current().id());
foo.b.push(44);
},
);
assert_eq!(foo.a, [1, 2, 3, 4]);
assert_eq!(foo.b, [11, 22, 33, 44]);
}
949デフォルトの名無しさん
2024/11/23(土) 18:47:58.14ID:phMWL2Cw950デフォルトの名無しさん
2024/11/23(土) 20:57:00.22ID:h7mzZyhg >>948
フィールドが可視なこと前提にしちゃっていいの?
フィールドが可視なこと前提にしちゃっていいの?
951デフォルトの名無しさん
2024/11/23(土) 21:58:14.47ID:phMWL2Cw >>950
そんな話までやるの?
どの言語でも同じ
必要なアクセスメソッドを用意するだけ
impl Foo {
pub fn new(a: Vec<u8>, b: Vec<u32>) -> Self {
Foo { a, b }
}
pub fn a_and_b_mut(&mut self) -> (&mut Vec<u8>, &mut Vec<u32>) {
(&mut self.a, &mut self.b)
}
}
そんな話までやるの?
どの言語でも同じ
必要なアクセスメソッドを用意するだけ
impl Foo {
pub fn new(a: Vec<u8>, b: Vec<u32>) -> Self {
Foo { a, b }
}
pub fn a_and_b_mut(&mut self) -> (&mut Vec<u8>, &mut Vec<u32>) {
(&mut self.a, &mut self.b)
}
}
952デフォルトの名無しさん
2024/11/23(土) 22:17:13.62ID:h7mzZyhg953デフォルトの名無しさん
2024/11/23(土) 22:29:09.24ID:wvnRoJ4J954デフォルトの名無しさん
2024/11/24(日) 01:29:38.03ID:4sDepkd+ スライスの内部を弄るのはunsafeだけど
その構造体の内部は安心安全だからunsafeがどこにも現れないんだな
その構造体の内部は安心安全だからunsafeがどこにも現れないんだな
955デフォルトの名無しさん
2024/11/24(日) 01:59:38.19ID:J3183MXo Vectorの標準機能
好きなところで2分割する方法
スレッドでま利用可能
fn main() {
let mut vec = vec![1, 2, 3, 4, 5, 6];
let mid = vec.len() / 2;
let (left, right) = vec.split_at_mut(mid);
println!("left: {:?}", left); // [1, 2, 3]
println!("right: {:?}", right); // [4, 5, 6]
// 両方のスライスを同時に変更可能
left[0] = 10;
right[0] = 40;
println!("vec: {:?}", vec); // [10, 2, 3, 40, 5, 6]
}
好きなところで2分割する方法
スレッドでま利用可能
fn main() {
let mut vec = vec![1, 2, 3, 4, 5, 6];
let mid = vec.len() / 2;
let (left, right) = vec.split_at_mut(mid);
println!("left: {:?}", left); // [1, 2, 3]
println!("right: {:?}", right); // [4, 5, 6]
// 両方のスライスを同時に変更可能
left[0] = 10;
right[0] = 40;
println!("vec: {:?}", vec); // [10, 2, 3, 40, 5, 6]
}
956デフォルトの名無しさん
2024/11/24(日) 02:07:14.81ID:J3183MXo vecの機能
chunks_mutを使用する方法(等分割)
指定したサイズで複数個のスライスの可変参照
fn main() {
let mut vec = vec![1, 2, 3, 4, 5, 6];
let mut chunks = vec.chunks_mut(vec.len() / 2);
if let (Some(left), Some(right)) = (chunks.next(), chunks.next()) {
println!("left: {:?}", left); // [1, 2, 3]
println!("right: {:?}", right); // [4, 5, 6]
left[0] = 10;
right[0] = 40;
}
println!("vec: {:?}", vec); // [10, 2, 3, 40, 5, 6]
}
chunks_mutを使用する方法(等分割)
指定したサイズで複数個のスライスの可変参照
fn main() {
let mut vec = vec![1, 2, 3, 4, 5, 6];
let mut chunks = vec.chunks_mut(vec.len() / 2);
if let (Some(left), Some(right)) = (chunks.next(), chunks.next()) {
println!("left: {:?}", left); // [1, 2, 3]
println!("right: {:?}", right); // [4, 5, 6]
left[0] = 10;
right[0] = 40;
}
println!("vec: {:?}", vec); // [10, 2, 3, 40, 5, 6]
}
957デフォルトの名無しさん
2024/11/24(日) 17:24:11.96ID:0kQqDut1 Rustで書いたら危険だけどCなら安全に書ける例を教えてくれ
958デフォルトの名無しさん
2024/11/24(日) 18:13:55.87ID:I2rtYfjq >>941
rayonは確かに標準ではなく外部だが
C/C++では今も作り出せていないrayonやtokioなどの基盤ライブラリを
Rustが生み出すことができた勝因は
標準ライブラリを最小限にして外部のクレートに多くを託す方針をとったため
それでもなお標準ライブラリだけに拘るならば
その>>940の例はrayonを使わずに以下のように書くことができる
std::thread::scope(|scope| {
let mut rest: &mut [i64] = &mut buf;
while let Some((area, new_rest)) = rest.split_at_mut_checked(AREA_SIZE) {
rest = new_rest;
scope.spawn(|| {
area.iter_mut().for_each(|n| {
*n = f(*n);
});
});
}
});
rayonは確かに標準ではなく外部だが
C/C++では今も作り出せていないrayonやtokioなどの基盤ライブラリを
Rustが生み出すことができた勝因は
標準ライブラリを最小限にして外部のクレートに多くを託す方針をとったため
それでもなお標準ライブラリだけに拘るならば
その>>940の例はrayonを使わずに以下のように書くことができる
std::thread::scope(|scope| {
let mut rest: &mut [i64] = &mut buf;
while let Some((area, new_rest)) = rest.split_at_mut_checked(AREA_SIZE) {
rest = new_rest;
scope.spawn(|| {
area.iter_mut().for_each(|n| {
*n = f(*n);
});
});
}
});
959デフォルトの名無しさん
2024/11/24(日) 18:18:22.12ID:ZV7M8h6P rayonってCから使えないの?
最近はたまにCから呼び出せるようにしたRustのクレートを見かけるよな
以前とは逆向きだ
最近はたまにCから呼び出せるようにしたRustのクレートを見かけるよな
以前とは逆向きだ
960デフォルトの名無しさん
2024/11/25(月) 09:33:08.05ID:SsaYg1Am 科学 + ンニュース 5ch
保守派もリベラル派も「自分の政治的信念に合致したニュース」を信じやすいという研究結果 [すらいむ★]
https://itest.5ch.net/egg/test/read.cgi/scienceplus/1732447647
コメントも含めて読むと
陰謀論が収まら無い理由が判明する
保守派もリベラル派も「自分の政治的信念に合致したニュース」を信じやすいという研究結果 [すらいむ★]
https://itest.5ch.net/egg/test/read.cgi/scienceplus/1732447647
コメントも含めて読むと
陰謀論が収まら無い理由が判明する
961デフォルトの名無しさん
2024/11/25(月) 15:15:08.59ID:TQeBxjwA >>957
Rustは安全なものでもunsafe付けたら危険になる言語
Rustは安全なものでもunsafe付けたら危険になる言語
962デフォルトの名無しさん
2024/11/25(月) 17:19:35.66ID:HD3K11z8 >>958
結局、全体の可変参照&mutがある時
・structは各フィールドの&mutを同時に安全に得られる
・スライスはsplit_at_mut_checkedで任意に分割したサブスライスの&mutを同時に安全に得られる
つまりunsafeの必要なく安全に同時に書き換え可能ということだね
結局、全体の可変参照&mutがある時
・structは各フィールドの&mutを同時に安全に得られる
・スライスはsplit_at_mut_checkedで任意に分割したサブスライスの&mutを同時に安全に得られる
つまりunsafeの必要なく安全に同時に書き換え可能ということだね
963デフォルトの名無しさん
2024/11/25(月) 17:20:53.69ID:HD3K11z8 >>961
unsafeは危険という意味ではなくて
C/C++と同じようにプログラマーがその部分のコードの安全性の責務を持ちなさい、という意味だよ
もしそれを危険と呼ぶならC/C++のコードは常に全てが危険
unsafeは危険という意味ではなくて
C/C++と同じようにプログラマーがその部分のコードの安全性の責務を持ちなさい、という意味だよ
もしそれを危険と呼ぶならC/C++のコードは常に全てが危険
964デフォルトの名無しさん
2024/11/25(月) 17:46:18.55ID:VupnR4Dz よくrustと他の言語で比較するときに条件を揃えてないのが多すぎる印象。
パフォーマンスで差が出る部分でHashMapがある。デフォルトのハッシュ関数が安全に振られてるからちょっと遅い。高速化するなら下記のような感じ。
use std::hash::BuildHasherDefault;
use std::collections::HashMap;
use rustc_hash::FxHasher; // より高速なハッシュ関数
// FxHasherを使用したHashMap
type FastMap<K, V> = HashMap<K, V, BuildHasherDefault<FxHasher>>;
fn main() {
// 高速なハッシュマップの作成
let mut fast_map: FastMap<i32, String> = FastMap::default();
fast_map.insert(1, "fast".to_string());
}
パフォーマンスで差が出る部分でHashMapがある。デフォルトのハッシュ関数が安全に振られてるからちょっと遅い。高速化するなら下記のような感じ。
use std::hash::BuildHasherDefault;
use std::collections::HashMap;
use rustc_hash::FxHasher; // より高速なハッシュ関数
// FxHasherを使用したHashMap
type FastMap<K, V> = HashMap<K, V, BuildHasherDefault<FxHasher>>;
fn main() {
// 高速なハッシュマップの作成
let mut fast_map: FastMap<i32, String> = FastMap::default();
fast_map.insert(1, "fast".to_string());
}
965デフォルトの名無しさん
2024/11/25(月) 17:55:45.25ID:VupnR4Dz 昔、PHPでHashDos攻撃でサーバーが止まるという問題があった。特定のハッシュ値を生成するようなパターンで速度が著しく低下する。なので今はwebで外部からデーターが送られて来る時は安全なハッシュ関数を使う。
このハッシュが安全かどうかで処理速度が変わるのだけど、他の言語では昔のままのが多い。それでrustとC++を比較して遅いとか言われる事がある。安全か速度か選べるから両方揃えて比較してくれ。
このハッシュが安全かどうかで処理速度が変わるのだけど、他の言語では昔のままのが多い。それでrustとC++を比較して遅いとか言われる事がある。安全か速度か選べるから両方揃えて比較してくれ。
966デフォルトの名無しさん
2024/11/25(月) 18:58:14.92ID:1VAZLaev FxHash使うと結構速度変わるんだよな
967デフォルトの名無しさん
2024/11/26(火) 10:38:32.10ID:OrSHBPPk rustとかでi32とかVecとかHashMapとかにmethodを勝手にimplして使うことについて問題とかないですか?
968デフォルトの名無しさん
2024/11/26(火) 10:56:47.14ID:+wgmkm+f coherenceの縛りがあるから勝手にimplすることはできない
969デフォルトの名無しさん
2024/11/26(火) 11:04:59.40ID:MMcFc6BZ なんらかの trait を impl するという意味なら好きなようにやって構わないが、複数の型に impl する必要がある場合 (多相性を利用することを想定する場合) を除いては関数として定義したほうが良いことも多い。
970デフォルトの名無しさん
2024/11/26(火) 12:22:11.23ID:qH2nLRZc >>967
まず技術的にはRustは孤児ルール(orphan rule)により他へ影響を与える汚染を防げる仕組みがあるのでコンパイルが通るなら大丈夫
新たなメソッドを増やすには自分で用意したトレイトの中で行うことになるのでその自作トレイトをuseしない限り他への汚染の影響は無し
したがってあとは有用性と可読性の問題かな
例えばジェネリックに処理するためのトレイト境界とその新たなメソッドを用意するのは有用かつ必須でよく行われる
単に自作型に変換したいだけならば新たなトレイトとメソッドを用意せずとも
impl From<既存型> for 自作型 して
let x: 自作型 = 既存型値.into(); など
まず技術的にはRustは孤児ルール(orphan rule)により他へ影響を与える汚染を防げる仕組みがあるのでコンパイルが通るなら大丈夫
新たなメソッドを増やすには自分で用意したトレイトの中で行うことになるのでその自作トレイトをuseしない限り他への汚染の影響は無し
したがってあとは有用性と可読性の問題かな
例えばジェネリックに処理するためのトレイト境界とその新たなメソッドを用意するのは有用かつ必須でよく行われる
単に自作型に変換したいだけならば新たなトレイトとメソッドを用意せずとも
impl From<既存型> for 自作型 して
let x: 自作型 = 既存型値.into(); など
971デフォルトの名無しさん
2024/11/26(火) 12:32:30.35ID:OrSHBPPk972デフォルトの名無しさん
2024/11/26(火) 19:48:39.21ID:/2XIgpnc Traitのimplが出来るのは型を定義したcrateかtraitを定義したcrateだけだから、他のライブラリには影響しない
メソッドの名前が被っていてもそのtraitをuseしないと使えないし、最悪useすることになってもtraitを指定してメソッドを呼べる
メソッドの名前が被っていてもそのtraitをuseしないと使えないし、最悪useすることになってもtraitを指定してメソッドを呼べる
973デフォルトの名無しさん
2024/11/27(水) 16:06:33.32ID:ddkklZcJ 「ツールの使い方覚えるだけ」
まさにそれ
まさにそれ
974デフォルトの名無しさん
2024/11/29(金) 21:54:35.06ID:/9dKvjaK こうすれば実行時に確定する値を&'staticにできるね
static HOME: LazyLock<String> = LazyLock::new(|| std::env::var("HOME").unwrap());
let home: &'static str = &*HOME;
static HOME: LazyLock<String> = LazyLock::new(|| std::env::var("HOME").unwrap());
let home: &'static str = &*HOME;
975デフォルトの名無しさん
2024/11/30(土) 00:45:06.70ID:6Z2K+eju unsafeとは危険という意味で合ってるが、魔女のようなものを狩る行動を意味しない
信念と行動が合致しない方が得だから合致しない
信念と行動が合致しない方が得だから合致しない
976デフォルトの名無しさん
2024/11/30(土) 18:20:12.51ID:D1SGYlac 所有者をスタック上に置くからライフタイム管理が必要になる
それを避けて&'staticするには3つの方法がRustで提供されている
(1) 所有者を最初から持たない
(2) 所有者をスタックに置かない
(3) 所有者を捨てる
それを避けて&'staticするには3つの方法がRustで提供されている
(1) 所有者を最初から持たない
(2) 所有者をスタックに置かない
(3) 所有者を捨てる
977デフォルトの名無しさん
2024/11/30(土) 19:42:09.81ID:g3xetMDU データをRustの外に置けば、ライフタイム管理から逃れられる
たとえばファイルに書いてしまう
たとえばファイルに書いてしまう
978デフォルトの名無しさん
2024/11/30(土) 23:10:39.19ID:D1SGYlac (1) コンパイル時に値が確定して静的に配置されるものが該当
(2) 実行時に値が確定してstatic変数に遅延配置させるものが該当
(3) 実行時に値が確定してleak()させるものが該当
いずれも&'staticで安全に参照できる
(2) 実行時に値が確定してstatic変数に遅延配置させるものが該当
(3) 実行時に値が確定してleak()させるものが該当
いずれも&'staticで安全に参照できる
979デフォルトの名無しさん
2024/11/30(土) 23:33:27.96ID:6Z2K+eju C++もスマートポインタがあるからポインタ管理を推進する側の勢力だった
だからC++を使わなくてもCで十分という意見に説得力があった
今では、管理に反対する奴も賛成する奴もどっちもC++に不満を感じている
だからC++を使わなくてもCで十分という意見に説得力があった
今では、管理に反対する奴も賛成する奴もどっちもC++に不満を感じている
980デフォルトの名無しさん
2024/12/01(日) 21:53:13.54ID:IuCKzQHf let や let mut を見たとたん、「だーめだ、こりゃあ。数値計算に使えねえ。fortranの方が余程ましだ。」
と思った。大体、letなんてBasicで出てきそうなワードを「変数束縛」という深刻な概念に結びつけている
時点で作った奴はセンスねえと思うわ。
と思った。大体、letなんてBasicで出てきそうなワードを「変数束縛」という深刻な概念に結びつけている
時点で作った奴はセンスねえと思うわ。
981デフォルトの名無しさん
2024/12/01(日) 22:06:15.87ID:s/x9f/ll ブラックフライデーで複オジポエムが続いてたかと思えばさらに輪をかけた常識知らずが来たw
レス数が950を超えています。1000を超えると書き込みができなくなります。
ニュース
- 外務省局長は無言で厳しい表情…日中の高官協議終了か 高市首相“台湾”発言で中国が強硬対応 発言撤回求めたか… [BFU★]
- 中国国営メディア「沖縄は日本ではない」… ★6 [BFU★]
- 政府、株式の配当など金融所得を高齢者の医療保険料や窓口負担に反映する方針を固めた [バイト歴50年★]
- 中国国営メディア「沖縄は日本ではない」…★7 [BFU★]
- バービー、 台湾有事の発言の波紋で「たまったもんじゃない」「高市さんに真意は聞きたい」「国民に向けて説明してほしい」 [muffin★]
- ナイツ塙が指摘のローソンコーヒーカップ、ロゴ「L」で誤解生みデザイン変更へ 在庫使い切る3か月後にリニューアル [muffin★]
- 日本政府「高市総理の発言は問題ないと伝え、中国総領事のSNS投稿は問題があると中国に伝えました😊」 [931948549]
- 【悲報】ゼレンスキー「高市早苗は生命を守り、国際的なルールに基づく秩序を擁護し、国家間の相互尊重を促している」 [616817505]
- 高市早苗、岸田政権(当時)に「台湾有事は日本の有事か」という質問をしていた [175344491]
- 【悲報】中国→日本行きの航空チケット、高市有事の影響で50万人分がキャンセルされる [834922174]
- 青椒肉絲、牛肉ではなく豚肉を使うのが本物だった
- ケンタッキーの○○○バーガーという予告がアレを想起すると話題に [523957489]
