Rust part26

レス数が900を超えています。1000を超えると表示できなくなるよ。
1デフォルトの名無しさん
垢版 |
2024/09/20(金) 22:18:38.38ID:c48cFuZJ
公式
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/
845デフォルトの名無しさん
垢版 |
2024/11/17(日) 13:22:59.92ID:dobbbVxQ
現実的なことを言うとRustの仕事は多くないからな
世の中的にはC++の方が多いし、それよりもC#やJava、JavascriptやPythonの方が多い
現状Rustを書ける人が少ないから組織としても採用しづらい、みたいなところもある
2024/11/17(日) 14:04:38.06ID:+vBbiqfq
Rustは欠陥が多すぎる。
847デフォルトの名無しさん
垢版 |
2024/11/17(日) 14:14:43.13ID:LOC+6QAG
>>846
C++と比べても桁違いに欠陥ない
2024/11/17(日) 14:17:04.13ID:+vBbiqfq
>>342
>RustはCの置き換えには最適だが
そんなことない。むしろ置き換えに適さない。

>>843
そんなことない。
2024/11/17(日) 16:20:28.69ID:QnncDtq4
Rust に (まだ) 足りないものはあるという意味では欠陥はあるが、設計が間違ってて改善の余地がないような欠陥は少ないだろ。
C の場当たり過ぎる設計に比べれば Rust はだいぶん綺麗だわ。
850デフォルトの名無しさん
垢版 |
2024/11/17(日) 17:47:06.07ID:ZjcPAB2G
C++は多段に増築して要らないものも多く
新しい仕様は良いけど広まっていなくて
標準ライブラリのインターフェイスを新たな仕様にすることもできなくて
初心者にとってC++はRustの何倍も複雑で学習難易度も高いのよ
Rustはシンプルに高機能でプログラミング効率もいいね
2024/11/17(日) 21:11:05.44ID:8SN0eeCN
C++はBoostあたりまでは良かったけどそれ以降は機能のゴミ箱
上品な言い方をすればキッチンシンク担当になった
2024/11/17(日) 21:56:59.22ID:/B1+r+jF
>>849
そうでもない。
2024/11/17(日) 22:25:57.84ID:rGJZLWmT
mordern c+で随分楽になったけど
2024/11/17(日) 22:26:17.33ID:rGJZLWmT
modern
2024/11/17(日) 22:37:46.32ID:lBJAP2+3
CをRustで置き換えたら劇遅になるから重要な部分は無理じゃね
2024/11/17(日) 22:55:33.70ID:HbSpYeRV
>>855
デバイスドライバを両方で実装して速度がほぼ変わらないことが立証されている
2024/11/17(日) 23:02:46.96ID:/B1+r+jF
>>856
それは、一般にデバイスドライバはシンプルなアルゴリズムしか使ってないからだよ。
858デフォルトの名無しさん
垢版 |
2024/11/17(日) 23:11:47.34ID:vlQbYPk+
同じアルゴリズムでRustが遅い例プリーズ
2024/11/17(日) 23:14:29.54ID:/B1+r+jF
>>858
unsafeを使わない限り、ほとんどのアルゴリズムがそれに当たる。
なぜなら、ほとんどのアルゴリズムが使えないから。
860デフォルトの名無しさん
垢版 |
2024/11/17(日) 23:19:43.73ID:ZjcPAB2G
>>859
ウソつき
861デフォルトの名無しさん
垢版 |
2024/11/17(日) 23:25:29.83ID:dobbbVxQ
安全側に寄せる部分でRustの方が基本的にコストかかるんじゃないの?
グローバルな可変状態はMutexが無いと書けない (アクセスの度にロックが必要) とか、Cellは実行時に借用チェックするとか、配列は基本的に範囲チェックされるとか

コンパイラは利用側を知り得ない (複数スレッドから呼ばれる可能性があると想定せざるを得ない) からMutexが必要だけど実際は無いと想定して良い、みたいなケースはありそう
2024/11/17(日) 23:28:19.03ID:/B1+r+jF
>>860
あなたも含めたここの連中は理解力が低い。
なお、俺には丁寧に説明する義務は無い。理解できない人はそのままでいい。
俺には関係無い。
863デフォルトの名無しさん
垢版 |
2024/11/17(日) 23:34:51.20ID:vlQbYPk+
>>859
unsafe使えば同等になるなら、どこかの誰かさん以外はRustが遅いとは思わないのでは?
とりま、unsafe使わない遅いコードさらしてみては?

ここの優秀な方々が「unsafeでもこうすればCと同等の速さだ!」ってコードを返してくれるかもしれん。
2024/11/17(日) 23:37:27.94ID:HbSpYeRV
>>861
そこはどの言語でも同じ
スレッドローカル変数を使う
RustでもMutexの必要はない
865デフォルトの名無しさん
垢版 |
2024/11/17(日) 23:41:13.09ID:8NoNC7dP
他のレスに「あなたは正しくない」とだけ書けば自分が賢いということになるなら、それほど楽なことは無いな
スマホさえ持ってれば小学生でも同じことはできるわけだし
2024/11/17(日) 23:53:16.59ID:wVREKDBU
100点オジと複オジはいつまでたっても進歩がないな
2024/11/18(月) 00:24:33.99ID:GfaceI2A
基礎的なデータ構造に unsafe が必要になるのは本当だ。
基礎は std で提供されるのでその上では unsafe の仕様が少なくなるように巧妙に設計されている。
std を使えないときに std と同等なものを作らなければならないような状況だと C とあまり差はない。
逆に言えば unsafe を含む下回りをかっちり作りさえすれば Rust のほうが優秀だよ。
2024/11/18(月) 02:14:46.19ID:Ui+tF1gu
あゝこんなときRustにもextern "C"があれば平和が訪れるのに
869デフォルトの名無しさん
垢版 |
2024/11/18(月) 04:44:45.38ID:IRvDm3R2
>>840
「欠陥のない言語は存在しない。だがデバッグの不可能な言語もまた存在しない」
2024/11/18(月) 07:01:58.78ID:rC7K9dh5
おれの作った言語はデバッグ機能ないけど?
871デフォルトの名無しさん
垢版 |
2024/11/18(月) 07:06:12.01ID:INV+aJIp
【ナゾロジー】サイコパスは「痛みを伴う失敗」から学習できない! [すらいむ★]
http://itest.5ch.net/egg/test/read.cgi/scienceplus/1731838156
2024/11/18(月) 08:33:03.50ID:boZQ3aHy
>>868
あるやる
2024/11/18(月) 09:04:25.28ID:92FA8ffy
>>867
>逆に言えば unsafe を含む下回りをかっちり作りさえすれば Rust のほうが優秀だよ。
そんなことない。
unsafeがライブラリ関数の外に染み出てくるから。
2024/11/18(月) 09:13:51.03ID:92FA8ffy
>>865
ここに書かないのは、「企業秘密的」な意味も有るんだよ。
875デフォルトの名無しさん
垢版 |
2024/11/18(月) 09:30:27.68ID:IRvDm3R2
>>862
競プロでもやってんの?
2024/11/18(月) 09:41:47.81ID:7J3JrtFR
>>873
RustがC/C++に勝利した一番大きな要因は
メモリ操作など基本的にunsafeにたどり着く様々な操作を
中身でunsafeを使っていてもそれを外へ染み出さないsafeなインターフェイスを提供して実用的に使えることを示した点にある
これがRustの標準ライブラリの中核であり
同様にしてunsafeが外へ染み出さないsafeなライブラリを作ることもできる
2024/11/18(月) 10:43:14.43ID:92FA8ffy
>>876
馬鹿発見。
878デフォルトの名無しさん
垢版 |
2024/11/18(月) 12:57:29.84ID:0TuJxtFY
>>873
unsafeの何が悪い
unsafe{
下回りもunsafe
利用者側もunsafe
皆で使おうunsafe
}
2024/11/18(月) 13:58:30.56ID:DtxKjacA
unsafeが染み出すとか言っているの本気?
意図的に出さないと出てこないよ?

// 意図的なunsafe
pub unsafe fn dangerous_operation() {
// 何らかの危険な操作
}

// 利用者側
unsafe {
dangerous_operation(); // ここでunsafeが必要
}

普通はこう書く

// ライブラリ側
pub fn safe_wrapper() {
unsafe {
// 内部で危険な操作を行うが、
// 安全性を保証する条件をすべて満たしている
}
}

// 利用者側
safe_wrapper(); // unsafeは不要
2024/11/18(月) 20:31:59.79ID:7J3JrtFR
>>877
事実を目の当たりにして具体的な反論や反例を出せない気苦労は理解するが
それでも具体的にRustのコードを示すのがよいかと
881デフォルトの名無しさん
垢版 |
2024/11/18(月) 21:05:40.46ID:K2lQU8l5
>>874
説明は求めないけどね?
「自分は知ってるが説明する義理はない」なんて第三者からみれば「俺は分かりません説明できないです」と書くのと変わらないじゃない
分からないならスルーすればいいのに、それをわざわざ書くのはダサくない?
882デフォルトの名無しさん
垢版 |
2024/11/18(月) 21:41:56.71ID:K2lQU8l5
実際にはunsafe使わないRustはCよりもいくらかオーバーヘッドが生じるとは思う
Cでなポインタのコピーで済むけどsafe RustだとArcが必要だからcloneの際にロックのコストがかかるとか、配列へのインデックスでのアクセスで境界チェックされるとか
Rustでは安全側に寄せる分のコストはかかるはず
2024/11/18(月) 21:52:16.61ID:k3+/8xDm
>>882
本当に各チェックを安全に外せる場合
つまり安全なインターフェイスを提供できる場合
Rustでもそれを安全なライブラリとして提供すればよいですね
実際にそのようにしてRustの標準ライブラリが作られて来ていますから
2024/11/18(月) 22:05:29.90ID:1mdid6am
>>879のコード例だと本当はアウトなのに屁理屈でセーフという俺ルールでねじ曲げてるだけに見える
それunsafeやない、アウトや!
2024/11/18(月) 22:35:51.22ID:SToHXvxk
計測して本当にunsafeにする価値がある部分だけ暴走覚悟でunsafeにすればいい
満たさないと危なくなる条件はdebug_assertしておくと気休めになる
886デフォルトの名無しさん
垢版 |
2024/11/18(月) 22:46:47.54ID:r0p6egBs
>いくらかオーバーヘッドが生じるとは思う
そんなレベルじゃないだろw
2024/11/18(月) 22:49:05.04ID:7J3JrtFR
>>882
安全のためのオーバーヘッドはどちらの言語も同じです

Rustも&TならばCopy実装型なのでコピー出来ますからC言語と同じです
Arcのcloneはロックフリーです
ロックされるのはその中で用いるMutexなど
C言語でも排他制御が必要なところではMutexが使われます
ヒープを使うデータをポインタで指す人数が変化していくならば最後の人が解放するためにリファレンスカウント管理が必要です
実際にC++ではそれがshared_ptrとしてArcと同様なものが提供されています
2024/11/18(月) 22:53:38.18ID:+RZAZC6X
よかった、RustとCではオーバーヘッドは同じがRustの方が少ないんだね
2024/11/18(月) 22:59:47.77ID:x8ZZBVl/
前提条件大杉
2024/11/18(月) 23:17:10.99ID:tFghvvKh
>>888
複おじ、幼稚すぎw
2024/11/18(月) 23:40:55.05ID:k3+/8xDm
Rc相当がなくArc相当のshared_ptrしかないC++はオーバーヘッドが大きい
2024/11/18(月) 23:52:07.17ID:dSfvQiDe
C++でポインタいじってる時も特定の前提条件の時まともに動くだけで、そこから外れたらすぐバグるから。安全性のレベルを合わせたら結局どちらも同じようなコードになるよ。条件チェックしてるのとしてないのを比較して速い遅い言われても。
あと、rustの方が型で前提条件弾いて全域関数を作りやすいから。下手なC++よりは最適化される場合もある。何にせよ最初ほ安全に振っておいて、そこからプロファイラかけて遅いところだけ変えて行くほうがいいと思うけどね。
893デフォルトの名無しさん
垢版 |
2024/11/19(火) 00:32:35.22ID:GSnhfwF9
参考までに聞きたいんだけど、画像処理みたいなタスクってunsafe無しでもC/C++と同等の速度を出せるの?
フィルタのように周辺画素の値を使う処理や、処理対象の画素 (もしく行) を複数スレッドに分割するような処理を想定してる

自分の知識だと、可変かつマルチスレッドのような場合はsafe Rustだと難しい気がしてる
unsafeを使うなら、オーバーラップしないように範囲を分割して、そのポインタを渡して処理させることはできるけど、safe Rustだと可変借用のルールが問題になる気がしてる
それこそunsafeを使うべき場面だというなら納得するし、safe Rustでもうまくやれるなら知っておきたい
2024/11/19(火) 00:50:32.75ID:FW/CGHup
>>893
rayon crateというデーター並列処理のライブラリを使う。チャンクに分割されたパラレルイテレータを回すだけ。フィルター処理とかは割と簡単。
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(())
}
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ラインずつ。ある程度のサイズにしたほうが高速になる。
チャンクのサイズを変えたらクロージャーの処理も変えるのを忘れずに。
2024/11/19(火) 02:14:25.94ID:FW/CGHup
これをC++で書けと言われたらやりたくない。
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使ってるよーって人います?
2024/11/19(火) 08:27:40.98ID:FW/CGHup
スレッド数を自分で設定したいって意味でいいのかな?
rayon::ThreadPoolBuilder::new().num_threads(8).build_global().unwrap();
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(|...| {
// 処理
});
});
902デフォルトの名無しさん
垢版 |
2024/11/19(火) 14:47:04.76ID:9IiXc5Vb
>>892
>下手なC++

templateですね判ります
2024/11/19(火) 15:24:29.64ID:+UtMc6V6
>>897
なんで主語がrustとc++なの?
便利なライブラリがあるってだけでしょ?
c++でも同様のライブラリを作るのは可能だと思うけど
2024/11/19(火) 15:42:39.43ID:s9mRA7mb
Rustが勝利した原因はrayonやtokioなどのマルチスレッドを便利に安全に活かすライブラリの存在が大きいが
C/C++は数十年の年月を重ねてもそれに匹敵するものが完成しなかった
2024/11/19(火) 16:37:47.00ID:Yysxm38B
>>903
発端は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. という説明)

問題なさそうなら使わせてもらいます
907デフォルトの名無しさん
垢版 |
2024/11/19(火) 22:46:22.71ID:jmJ5BpPK
C++で並列とかようやらんわ
SendもSyncもないとかもう考えられん
908デフォルトの名無しさん
垢版 |
2024/11/19(火) 22:49:56.47ID:126iZ9C9
違うかも?
>>906 のスレッド4つの例だと、クロージャー自体はプール内のスレッド(スレッド1とする) で実行されて、スレッド1はpar_iterで並列処理を開始した後すぐ抜けて par_iter の仕事に加わるということ?
2024/11/20(水) 00:33:04.50ID:shrZYon3
例えばスレッドプールを4で設定するとワーカースレッドが4つになります。でそれとは別にメインスレッドがあるわけで、このパラレルの処理をするときはメインスレッドもワーカーとして参加します。なので5個で回る感じ。
2024/11/20(水) 00:36:52.89ID:ijtcomF1
pool.installとpool.scopeでメインスレッドがワーカーとして参加するかしないかが変わるみたい。
2024/11/20(水) 00:42:34.33ID:e0+ziHsU
>>907
C++にasyncがあるぞ。
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),
}
}
2024/11/20(水) 01:09:41.69ID:ijtcomF1
>>911
asyncは全然別の話。
rustでは型に対してsendやsyncといった属性を付けるようなイメージ。sendが付いてなければ別スレッドにデータ渡せないとかsyncが付いてなければ同時に使えないとか、そういうスレッド対応してないものを使うとコンパイラに怒られる仕組みになってる。
914デフォルトの名無しさん
垢版 |
2024/11/20(水) 08:50:31.70ID:yTy4Ahlp
>>912
詳しい説明ありがとう
scope と install については自分でもちょっと調べてみます
2024/11/20(水) 09:59:28.14ID:MYLVUJ4i
最近のCPUは速過ぎるから第三者から見れば「速さ」は見えない
バグなら見える

それで無人の機械で速さを計測するから
第三者などという人間は不要だと分かる
2024/11/20(水) 11:26:15.05ID:W8mVvsIh
Cが早くてRustが劣っていると仮定して
その差が問題なることなんてない
自分では何も生み出せないベンチ回マニアくらいだろ
2024/11/20(水) 12:43:18.25ID:/wT43F1g
>>914
フィルター系のプログラムだとCPUのSIMD命令がかなり効くと思うんでそちらも検討するといいかと。
コンパイラが自動でやってくれる可能性もあるけど、明示的に書くと確実。
標準だと std::simd がそのうち実装される予定。
その他クレートもあるんで探してみて。
2024/11/20(水) 13:08:23.05ID:LXAOodJ8
一般的なサイズの画像の全ピクセルをO(N)で舐める程度ならシングルスレッドで十分じゃね?まあSIMDはアリだが
ガチで速度出したいのって多数のファイルをバッチ処理するようなケースが多いから、
そういうときは結局ファイル単位で並列処理した方がスループット高かったりするんだよね
タスク内の並列化の方が技術的にはチャレンジングだからやりたくなる感情は理解するけどね
2024/11/20(水) 14:17:41.03ID:nL8S8oi5
>>879
馬鹿。
2024/11/20(水) 14:56:07.23ID:ytG52ull
>>918
横からだが、画像フィルタは単なるわかりやすい例として出てるだけだろうから画像サイズなどは関係ない
一般的に多量のメモリ上でのある程度の計算処理が必要で、それがエリア分けして並列可能なら、並列化の検討余地が出てくる

ファイル処理などの件はIOバウンド特にリモートだとIO待ちが顕著になり別の対策が必要になってくる
一番極端な場合はtokioを使って並行並列化が最も速くなりうる
つまり1件に対して1スレッドではなく、1件に対して1タスク(async軽量タスク)を割り当て、1スレッドで複数のタスクが同時に並行に動く形になる

rayonのケースでもtokioのケースでも、利用する並列スレッド数は物理コアスレッド数を上限とする形
2024/11/20(水) 21:20:24.03ID:LXAOodJ8
>>920
高説ごもっともだけど、多数のファイルのバッチ処理をするときには分割しないで1スレッドの方がスループットが高い説自体は間違ってはいないでしょ
SIMD含めスレッド内での最適化は尽くしていて単一プロセッサを100%使い切っているのであれば、
マルチスレッドに伴う諸々のオーバーヘッドやアルゴリズムの複雑化を避けられるから自明
もちろんシングルスレッドだとプロセッサ数に対して件数が十分に多くなきゃスループット落ちるしレスポンスも当然劣るから、一般にどちらが良いということではないが
2024/11/20(水) 21:35:21.34ID:5+HdYMGb
>>921
>>分割しないで1スレッドの方がスループットが高い

おかしい
どういう意味と根拠?
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バウンドな) 並列処理についての話が出たと思えば有益な情報だと思う
2024/11/20(水) 22:00:47.56ID:V/GV/ca9
>>923
スレッド起動以外にもマルチスレッドのオーバーヘッドはあるし、マルチスレッド化できるけど効率が悪化する画像処理アルゴリズムなんていくらでもある
それを誤差レベルとして無視できるかどうかはタスクや状況次第だが、いずれにせよゼロではない
2024/11/20(水) 22:03:31.92ID:ytG52ull
>>921
前提と何をするかによって変わりうるかな
例えばちょっと見方を変えるとそれと同種の、多数の人たちから色んなリクエストが来て処理して返す場合、つまりHTTPなどの各種サーバー類の場合
tokioを使ったマルチタスク・マルチスレッドが最も効率がよい
1つのCPUで最も多くの人数を同事に捌くことができる方法になると実証されている
2024/11/20(水) 23:45:54.40ID:5+HdYMGb
>>925
複数の対象があると最初に言ってるのだから
個々の処理がマルチスレッドに不向きなアルゴリズムであっても
複数の対象を並列化すればよい
なぜアルゴリズムが複雑化すると思うのか?
アルゴリズムはそのままでいい
既出のrayonのコード例でも同じ処理(アルゴリズム)が並列に動くだけでありアルゴリズム部分に手を入れずに並列化できている
2024/11/21(木) 00:43:39.12ID:7teRxqa+
コードのサンプルはもっと複雑なのも考えたけど、ここじゃ載せきれないからシンプルにしたよ。この程度ならシングルスレッドでもすぐ終わるのはたしか。
でも複雑な画像処理ならCPUキャッシュのヒット率の方が処理速度に影響するんでキャッシュ溢れないように1つの画像をマルチスレッドで処理した方が速いかもしれない。
非同期が効くのはI/Oメインの処理の場合。何事も用途によりけりだよ。
2024/11/21(木) 00:47:13.55ID:iDAcMnOY
DllMainの引数を確認するべきじゃね?
スレッド起動毎に呼ばれるんだからオーバーヘッドが誤差は言い過ぎ
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
2024/11/22(金) 06:49:29.53ID:VaeItC08
>>931
Rustで作ると遅いんだよな
933デフォルトの名無しさん
垢版 |
2024/11/22(金) 10:51:02.29ID:vbb23urH
The Rust Programming Language:
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にすればいいじゃん。
2024/11/22(金) 18:39:10.11ID:y0TICFrd
そのキーワードをunsafeではなく「ハイリスクハイリターン」にでも
変えれば生霊が成仏するような気がする
リスクを100倍にすればリターンも100倍になるってのはただの物語にすぎないと個人的に思うが
科学だと思ってる人間がいても別に驚かない
2024/11/22(金) 18:50:58.98ID:MEPFF+NK
>>882
C/C++/Rustのオーバーヘッドは同じ
メモリ管理もポインタで別主体の複数箇所から指すならC++のshared_ptrやRustのRc/ArcのようにCでも参照カウンタを持つしか安全に解放できない
938デフォルトの名無しさん
垢版 |
2024/11/22(金) 22:18:31.82ID:TcJB6S+5
>>935
部分借用のケースあるじゃん
スレッド1がバイト列の前半を、スレッド2が後半を書き換える場合
これは理屈上はロックが要らないけどsafe Rustだとルール上ロックが要るケース
2024/11/22(金) 22:39:33.83ID:y0TICFrd
a 形式だけで安全といえる
b 中身をよく見れば安全といえる
c 形式も中身も危険

unsafeの部分はbとcが混ざっている
(bの価値がaより高いとは言ってないし安いとも言ってない)
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;
});
});
}
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の方が良いと思ってるので、言語に対する批判ではないと思って欲しい)
2024/11/23(土) 11:04:40.44ID:AT4bo2Ti
RustでもCでもロックが不要な例を出してはいけない

また「Cでは不要」の部分だけを自分で検証して残りは他責にするのは
近似としては悪くないが厳密には悪い
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() }
}
}
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);
});
});
}
レス数が900を超えています。1000を超えると表示できなくなるよ。
5ちゃんねるの広告が気に入らない場合は、こちらをクリックしてください。

ニューススポーツなんでも実況