[過去ログ] Go language part 5 (1002レス)
前次1-
抽出解除 必死チェッカー(本家) (べ) 自ID レス栞 あぼーん

このスレッドは過去ログ倉庫に格納されています。
次スレ検索 歴削→次スレ 栞削→次スレ 過去ログメニュー
937: デフォルトの名無しさん [sage] 2025/05/19(月) 09:24:27.09 ID:8khPYfEx(1/10) AAS
間違い訂正 >>885
✕ 平行(coherency
○ 平行(concurrency
まあ知ってりゃ分かる範囲だが
938: デフォルトの名無しさん [sage] 2025/05/19(月) 09:25:09.06 ID:8khPYfEx(2/10) AAS
asyncについてはお前らのほうが詳しいようだから任せるが、俺が言おうとしてたのは、
「キラーアプリ/キラーコンテンツ」と同様に、プログラミング言語にも「キラーコンセプト/キラー文法」があり、
これがJSは「I/Oの分離」で、Goは「Goroutine」という事

まあざっくり関係ある所だけ詰めておくと、
>>887
> Javascriptでフロントエンドプログラム初心者が簡単に使えるから流行っただけ (887)
なるほどお前がJS大嫌いなのは分かったが、Rustの馬鹿信者共と同様、お前も何故JSが蔓延ったのかを考えるべきだ
Rustとは違い、JSはガチで蔓延ってるからな

> async/awaitの発祥はC# (F#)だけど (887)
『文法』についてはその通り。ただし非同期シングルスレッドの『コンセプト』を全面的に打ち出したメインストリーム言語はJSが初だ
と言うより、2000年頃はJSはオモチャ扱いされてたが、
パフォーマンスや記述の容易さにおいて優れた言語であることを実証し、実力でメインストリームへと駆け上がってきた
この原動力になったのが「非同期」で、実際、現時点のメインストリーム言語はだいたい非同期をサポート『するハメに』なっている
(=JSが非同期でなかったら、他言語がここまで早くasyncをサポートすることも、またC#がasyncを思いつくこともなかったと俺は見ている)
同様に、多言語で普遍的なコンセプトはオブジェクト指向やクロージャ位だろ
逆に言えば、asyncはこれらに並ぶ発明、とも言える

> JSが勝ったのは、それがブラウザで動く事実上ただ一つの言語だから (889)
一応Javaも使えた(らしい)が…(誰も使わないので2016頃にブラウザから落とされた)
まだDOMのAPIに痕跡も残ってたはず
そしてお前にとっては実はこれはラッキーな話で、JSがブラウザ内に留められていた、と認識したほうが正しい
もしJSが当初からコンソール等でも使えたら、多分Pythonが駆逐されてた
(俺にとってはこうなってくれてたほうが良かったが)
939: デフォルトの名無しさん [sage] 2025/05/19(月) 09:25:50.19 ID:8khPYfEx(3/10) AAS
> 別にシングルスレッドでの並行処理が良いなんてことはない
これはお前の認識が間違ってる
非同期で平行処理をさばいたほうが「同期/マルチスレッド」よりも性能が出るので各言語はasyncをサポート『するハメに』なった
これはお前も(JS大嫌いなので認めたくないようだが)、以下のように認識できてる
> 理想的にはasyncの方が効率的になり得ると思うけど (889)

C#もそうだが、Thread->(何かあったと思ったが忘れた)->BackgroundWorker->Taskまでは、
それまで通常の同期型マルチスレッドでしか無い
というのはまあ、言い方が悪いのは認める
なんせマルチスレッドは元来非同期であって、つまりmutex等の同期機構が必要な「ガチの非同期」であり、
JSの「なんちゃって非同期」で「非同期」を極めたつもりになってる馬鹿JSer共は俺も全員殺したい位だ
ただ一般的に、また特に初心者に対しては「文法」が目立つので、「非同期」「非同期」言われ、「非同期」がすごいのかと勘違いしがちだが、
JSのコンセプトは「I/Oの分離」で、その手段が「非同期」だっただけ(そして強制=I/Oに同期APIがほぼ無い)
ここをお前は勘違いしてて、すごいのは「非同期」自体ではなく、「I/Oの分離」だ
(ただしJSではI/O===非同期の為、見た目わかりやすい「非同期」が用語として使われることが多い)

何が違うかというと、切り出しの粒度が違う
Goroutine含めたマルチスレッドは、I/Oをスレッド内で何度でも処理出来る
つまりかなり大きな単位で切り出してる。これは後述するがスイッチングコストの問題もあるから
これに対し、JSが求めたI/O分離は、各I/O毎に一つとする最小粒度でasyncに切り出し、
ただこれだけで十分だ、これ以外は切り出す必要もない、というわけ
(だから切り出し粒度の面でもそれまでのマルチスレッドからすると異端)
940: デフォルトの名無しさん [sage] 2025/05/19(月) 09:26:28.98 ID:8khPYfEx(4/10) AAS
もう一度整理すると、
他言語「全然処理能力が足りない!もっとCPUを寄越せ!!くらえマルチスレッド昇竜拳!!!」
JS「いや書き方変えてI/Oを分離すれば、実はCPUなんて一つで足りてる」で、
GreeJS「ボクはマルチスレッドの倒し方、知ってますよ?」てなところだ
実際JSの性能が良かったから、他言語はJSを参考にI/Oを非同期化するための文法を導入『せざるを得なく』なった
というのを885で書いたつもり(まあどうしても「非同期」が目立つが)

駄目押しで言っておくと、
「非同期」で書いた方がパフォーマンスが出てしまったから、C#含め各言語は「非同期」文法を導入『せざるを得なく』なった
そしてこれを世に知らしめたのがJSで、結果、JSはプログラミング言語全体をリードする形になり、蔓延る事になってる
逆に言えば、2000年頃にC#がasyncを導入してたら、今頃C#はJSを超えるシェアだっただろうし、
同様に、GoがJSと同時期(1995)に発表され、Goroutineで『I/Oを』分離する、というコンセプトだったら、GoもJS程度には普及してたはず
つまりJSはその当時、誰も思っていなかった「金脈」を掘り当てた結果、報酬として蔓延る事になった、とも言える
941: デフォルトの名無しさん [sage] 2025/05/19(月) 09:27:03.65 ID:8khPYfEx(5/10) AAS
でまあ、889のリンク先読んだが、その筆者やお前がasync大嫌いなのは分かった
そしてその中でも言及されてるが、実際の所、I/OはOS内でasyncになってるから、
同期APIしか使ってないマルチスレッドでも自動的にasyncになるのは事実だ
ただ、OSレベルではなく、プログラミング言語レベルでasyncにしてしまえば、
パフォーマンスでぶち抜ける事をJSが発見してしまった

実際何が違うの?といわれれば、スタック含めたコンテキストスイッチングが最小に押さえられ、
スタックも浅く小さく抑えられるのでキャッシュヒット率が上がる、程度のはずだが、
結局の所はこれが無視出来ないからパフォーマンスが出てしまってる
つまり、
他言語「OSでasyncになってるからヨシッ!」
JS「いやコンテキストスイッチングをゼロにしてキャッシュヒット率上げれば全然行けるで!!!お前らまるで見えてねえな」
でJSが正しかったから、JSモドキなコンセプトをasync文法として採用『せざるを得ない』状況になってるわけ

ただしこれが良いか悪いかは確かに微妙である
その筆者は「色が付いて(=同期関数か非同期関数か分からないので)使いにくい」というわけだが、
これはその筆者がJSを知らないだけで、JSはI/Oが非同期になってるだけなので、関数名見れば分かる(ように作る)
ただ、I/Oが全部非同期で強制なら、理屈的には、(プログラマによる明示的な記述無しで)全自動で非同期に出来るはず
これに近い事をコンパイラにやらせているのがC#だし、generator(コルーチン)な実装にすりゃ出来るだろというのもその通り
明示的にプログラマにI/O分離させた結果、同期よりは見にくいソースコードとなるのは事実
自動化出来てればもっと上ではある
(そして他言語はOSで十分に自動async化出来てると勘違いしてたのをJSが指摘した形になる)
942: デフォルトの名無しさん [sage] 2025/05/19(月) 09:27:53.50 ID:8khPYfEx(6/10) AAS
だからGoが普及する為には、JS同様に何かしら「金脈」を掘り当てる必要がある
それが出来てないから今がある

Goの場合の想定「金脈」はGoroutine、
Java流に言えば、"Write once, perform anywhere"(一度書けばどこでも最大性能)だが、
実際の所はGoroutineのスイッチングコスト(とチャネルの通信コスト?)が高すぎて、最小粒度ではパフォーマンスがまるで出ない
逆にこれが出来てるのはGPU/CUDAであり、同じゲームプログラム(シェーダープログラム)で、
それぞれのハードウェアでの最大性能が出る
だからベンチでGPU毎のfpsがずらりと綺麗に並ぶ事になる

敗因は何か?と考えると、
・JS以外の他言語と同様、スイッチングコストを甘く見すぎ
・スイッチングコストを下げる努力をしてない、というよりプログラマ側の努力で下げられない
 (当然だが同一/最小粒度のままで。粒度を上げてスイッチングコストを下げるのは本末転倒)
かと。逆にJSは
・プログラマに強制的にI/O非同期化の努力をさせ、スイッチングコストゼロを目指す
というコンセプトが当たったから今がある
943: デフォルトの名無しさん [sage] 2025/05/19(月) 09:28:31.40 ID:8khPYfEx(7/10) AAS
> Goは「普通の関数をそのまま並行に動かせる」感じなので、その手軽さが好まれてると思う (989)
> CPUバウンドな計算には向かないけど、IO中心のタスクなら十分に良い性能にはなるので
さらに駄目押ししておくと、I/OバウンドならPythonやPHPでも問題ない
だから問題なのはCPUバウンドの場合だが、
JSは「お前らがCPUバウンドと勘違いしてるのは、実はスイッチングコストバウンドだ。本当のCPUバウンドはまだ先にある!!!」として
『手動で』I/Oを非同期分離する事をプログラマに要求し、
(実際ウザイのも確かだが)やってみると確かにパフォーマンスが出るので、
他言語も同様の仕組みを導入『せざるを得なく』なった
もしGoroutineが本当に素晴らしければ、他言語も同様の仕組み、
つまりマルチスレッドをもっとお手軽に記述出来る文法を導入せざるを得なくなる
ただ、そうではなかったので、そうなってない
つまり、他言語から見て、Goroutineは真似る価値もない

そしておそらく
> 「普通の関数をそのまま並行に動かせる」
これが駄目なんだよ
GPUはスイッチングコストがゼロになるようにハードウェアが作られているが、それでもプログラムにはだいぶ制限がある
メチャメチャざっくり言うと、通常はとりあえず1024スレッドを目指すので、レジスタは64本に制限される
なおスタックは元々無い。だからx86CPU(レジスタ8本)だとイメージとしては
・スレッド当たりのスタックは224Bytes(=56*4)
となる。勿論、スタックを消費するタイプの再帰は出来ないし、コード上の変数の数も制限される(≒最大63変数、1本はPCなので)
対してGoroutineには何の制限も無いだろ
そりゃスタックも大きくなるしスイッチングコストも結果的に上がる
(=キャッシュヒット率が下がる。まあGPUにはCPU的文脈のキャッシュもないが)
944: デフォルトの名無しさん [sage] 2025/05/19(月) 09:29:12.15 ID:8khPYfEx(8/10) AAS
だから今すぐ出来る対策は、Goroutineのスタックサイズ制限でのスイッチングコスト低減だろうよ
コンパイラで各Goroutine毎の最大スタックサイズを静的に解析し、そのサイズに固定する
静的にスタックサイズを確定出来ないGoroutineのコードは、落とす(=エラーとしてプログラマに書き直させる)、とかだね
(GPUは既にこうなってる《はず》)

とりあえずGPUでは"Write once, perform anywhere"出来てるのだから、
・依存性がない最小単位でGoroutineに分離/分割し
・スイッチングコストをゼロに出来れば
行けるはず。ただ、Goはこのどちらもやろうとしてないよね

これも駄目押ししとくと、
Go「グリーンスレッドだから軽い」
GPU/CUDA「Goroutineなんて贅肉多すぎのデブスレッド。本当のマルチスレッドを見せてやんよ」
てなところかと
965: デフォルトの名無しさん [sage] 2025/05/19(月) 23:46:27.40 ID:8khPYfEx(9/10) AAS
>>946
> あとGoよりシングルスレッドの方のNode.jsの方がパフォーマンス出るとか言ってるのはお前だけだから、ソースを出せ
お前は現実を直視しろ
(ちなみに俺が言ってるのは個々のフレームワークやバイナリの話ではなく、モデルの話だ)
しつこいようだが纏めると、

従来型のマルチスレッド:
 スレッド間:シグナル、ロック、通信
 スレット内:同期APIを使う。I/OはOSレベルで自動的に非同期
 起動単位:JOB単位(=JOB毎に1スレッド)
 アクティブスレッド数:CPUと同数以上
 狙い:多数のスレッドで性能を上げる

Go型のマルチスレッド:(=従来型の発展型)
 スレッド間:通信
 スレット内:同期APIを使う。I/OはOSレベルで自動的に非同期(なおGoroutineで非同期にも書けるからasync文法は必要ない)
 起動単位:JOB単位、またはもっと小さく、データフロー単位(=1つのJOBを多数のGoroutineに分割)
 アクティブスレッド数:CPUの数倍以上
 狙い:かなり多数のスレッドでさらに性能を上げる

JS型のマルチスレッド:(=アンチマルチスレッド)
 (スレッド間:通信)
 スレッド内:非同期APIを使い、プログラマが手動でI/Oを非同期化
 起動単位:全部(またはできるだけ多数)のJOBを一つのスレッドで処理する
 アクティブスレッド数:出来れば1、または最小
 狙い:マルチスレッドにおけるオーバーヘッドを無くすため、「出来るだけ少ないスレッド」に集約する
966: デフォルトの名無しさん [sage] 2025/05/19(月) 23:46:56.13 ID:8khPYfEx(10/10) AAS
で、従来型よりJS型の方がパフォーマンスが出ることが分かってしまったから、あらゆる言語がasyncを慌てて導入することになってる
だからasyncを導入した言語は、自ら敗北を認めてる
ただまあ、確かにGoはこの意味では負けを認めていないな

とはいえ、「出来るだけ少ないスレッド」という、マルチスレッドを根本から否定するJS型が勝ってしまった意味は大きい
そしてGo型は従来型をさらに発展させたものなのだから、お前らに危機感がないのはだいぶ狂ってる
この意味でなら、Goは負けを認めず、負け筋に乗り続けてるだけ
(だから今後共負け続ける)

Go型でJS型に勝つためには、スレッドスイッチのコストを最小化することが必要だが、Goはこれをやろうともしてない
だから、Goに勝ち筋は今の所無い
前次1-
スレ情報 赤レス抽出 画像レス抽出 歴の未読スレ AAサムネイル

ぬこの手 ぬこTOP 0.208s*