アカウント名:
パスワード:
が実装されるっぽいです。
変な話ですけど、priority inheritanceはちゃんと実装するんでしょうね? 現状の実装を見たら目が点になったので...
あと、C言語上で同じ文であってもarchitectureによってlockが必要だったりいらなかったりすることがありますよね(i386はsparcなどほかのarchitectureに比べてhardwa
最近の2.4は追ってないけど、初期のではlockの種類を問わずpriority inheritanceが全く行われていなかったような。それから、Linux kernelで特に問題になっていないように見えるのは、まだmainstream kernelに対してdispatch delayを意識するapplicationが存在しないという背景があります。Solarisの時にはこれが初期から大問題になり(主にinterrupt threadとrealtime process、特に前者はシステム全体に響く)、結局priority inheritanceがpreemptive kernelとならんで強烈に効いたわけです。
memory barrierについては、最大の敵は「人間」です。Cで書いた文が一体どのようにassemberに落ちるのかがわからないといけないので、発見には手間がかかります。実際、i386では平気だと思っていたものがsparc64ではうまく動かず、lockのかけなおしをする羽目になった経験があります。Linux kernelの基本方針はi386に似せた抽象化なので、よくよく注意しないと救えないarchitectureが出てくる恐れすらあります。
聞き伝えですが、sparc64の場合はi386と違ってmemory accessをout-of-orderにやってしまうことが多いそうです(並列度を上げるためにはしょうがないけど)。したがって、memory barrierを置いたとしても、それまでに完了して欲しいwriteがmemory barrierにぶち当たるまでに確実に実行することが保証できません。当時の議論を読み返して気が付いたのですが、これはhardwareの問題であり、softwareではmemory barrierよりも高級なlock(せいぜいmutexで済むのが救いだが)を使うしかありません。
それから、このような問題はある構造体のたった1つのmemberを読むだけでも起こり得ます。したがって、kernelのほぼ全てに渡って影響を及ぼします。そのような問題に対してmachine-dependentな対策をとった場合、特定のarchitectureでしか現れないbugをkernel全体にばらまいてしまう恐れがあります。
そういうわけで、FreeBSDではこの問題をmachine-independentなlock primitive(実際にはsleep mutex)で解決することにしました。これならsys/kern以下のlockに関わる問題をi386で解決すれば、sparc64でもその恩恵をそのまま受けることができます。
386では問題なかった -> 字面上の命令の順序は問題なかった -> それでsparcで問題がおきたということはストア命令が他のプロセッサから違う順番で見えた ->* membar #Syncを入れると良い
*の部分ですが、問題が起きるのはC言語上では1つの文(たいていは式文)でありながら、assemblerに落とすと複数回のstoreを必要としてしまう場合です(2重以上の間接参照をdereferする場合など)。この場合はC言語ではそれ以上式を分割できないため、C言語のレベルでは解決できません(マクロなどは一切使えない)。
ではdereferenceを全てバラしてcompilerが頑張ればいいかというと、そうもいきません。一般にあるdataがthread-localであるか否かを自動的に判断するのは(特にpointerの値を簡単にいじることができ、かつそれが必要になる場面では)技術的に困難な問題を抱えてしまいます。かといって全てにmemory barrierを張ると、並列度が落ちて無駄にperformanceを悪化させる結果になります。ならばassemble listに手を加えて...というのは、すでに4.3BSDで失敗しています。
memory barrierはあくまで1つのinstructionだけに対して同期をとるための手法です(その点ではi386のlock prefixと変わらない)。したがって、test-and-setやconditional storeなどの命令と併用するぐらいしか有効な使い道はありません。
なお、上述の問題はinstruction setについてmemory accessを何回認めるかに対する考え方の違いが原因です。したがって、この問題は10年、20年、50年経っても解決を見る見込みはありません。とならば、いたずらに問題を複雑化させるよりも、より問題を(machine-independentにすることにより)発見しやすくしておく(より多くの人が再現実験に加われる)努力をすべきです。最適化はその後でも遅くありません。
n重参照のdereference(n>2)は、例えば
p->p_pgrp->pg_jobc == 0
の左辺ですね。これはsignal処理の中で出てきた例(実際に問題になった)ですが、ほかにもprocess groupやsessionをprocessからたどる場合によく起こります。FreeBSDに関していえば、KSE(Kernel Scheduling Entity)のmergeにより、processももはや出発点ではなく、threadに貼りつくだけのものになってしまいました。ですから、
td->td_proc->p_pgrp->...
というdereferenceもぼちぼち出てきてます。まぁ、Cのレベルで複数の式文に分けることはできますが、実際にキーを打つ立場としてはそれをやると読みづらいし、あちこちいじらないといけないし、ローカル変数の初期化を忘れて...など、面倒なことの方が多いです(そんなことに時間を割く余裕はない)。
また、このような文を書いた場合、アドレス値のloadを複数回、しかも一般には不連続に(loadだけを連続実行することができない)繰り返すことになります。こうなるとmemory barrierだけではloadの間に入った別の命令を超えた保護ができません。
より多くのコメントがこの議論にあるかもしれませんが、JavaScriptが有効ではない環境を使用している場合、クラシックなコメントシステム(D1)に設定を変更する必要があります。
ソースを見ろ -- ある4桁UID
新機能 (スコア:5, 参考になる)
2.5で入るかもしれない機能のなかではプロセスごとにファイルシステムの名前空間を分ける機能(CLONE_NAMESPACE?)と入出力のより一般的な扱い(マルチキーボード、マルチディスプレー、マウスによる複数端末としての利用)に期待しています。
あとは
が実装されるっぽいです。
Re:新機能 (スコア:5, 興味深い)
変な話ですけど、priority inheritanceはちゃんと実装するんでしょうね? 現状の実装を見たら目が点になったので...
あと、C言語上で同じ文であってもarchitectureによってlockが必要だったりいらなかったりすることがありますよね(i386はsparcなどほかのarchitectureに比べてhardwa
Re:新機能 (スコア:3, 興味深い)
現時点でLinuxのパフォーマンスの分析した記事や論文を見る限り、そのへんが実際に問題になっているというデータはない(僕の知る限り)ので、2.5ではやらない or 後回しじゃないでしょうか。
メモリバリアはバグとかはあるかもしれませんが、そこそこ多様なメモリモデルに対応できるプリミティブが用意されてて、一応書くべきところには書いてあるように読めます(実は大量に抜けがあったりするのかも)。
Re:新機能 (スコア:3, 参考になる)
最近の2.4は追ってないけど、初期のではlockの種類を問わずpriority inheritanceが全く行われていなかったような。それから、Linux kernelで特に問題になっていないように見えるのは、まだmainstream kernelに対してdispatch delayを意識するapplicationが存在しないという背景があります。Solarisの時にはこれが初期から大問題になり(主にinterrupt threadとrealtime process、特に前者はシステム全体に響く)、結局priority inheritanceがpreemptive kernelとならんで強烈に効いたわけです。
memory barrierについては、最大の敵は「人間」です。Cで書いた文が一体どのようにassemberに落ちるのかがわからないといけないので、発見には手間がかかります。実際、i386では平気だと思っていたものがsparc64ではうまく動かず、lockのかけなおしをする羽目になった経験があります。Linux kernelの基本方針はi386に似せた抽象化なので、よくよく注意しないと救えないarchitectureが出てくる恐れすらあります。
Re:新機能 (スコア:1)
これについては強く同意します。んで
>> 実際、i386では平気だと思っていたものがsparc64ではうまく動かず、lockのかけなおしをする羽目になった経験があります。
これですが(gccですが)sparcの方に__asm__("membar #Sync":::"memory")、86の方に__asm__("" ::: "memory")とか書いてはダメでしょうか? 86では何もしなくてよくてsparcではlockが必要になるという状況が思いつかないのですが、支障がなければ教えてもらえないでしょうか?
Re:新機能 (スコア:3, 興味深い)
聞き伝えですが、sparc64の場合はi386と違ってmemory accessをout-of-orderにやってしまうことが多いそうです(並列度を上げるためにはしょうがないけど)。したがって、memory barrierを置いたとしても、それまでに完了して欲しいwriteがmemory barrierにぶち当たるまでに確実に実行することが保証できません。当時の議論を読み返して気が付いたのですが、これはhardwareの問題であり、softwareではmemory barrierよりも高級なlock(せいぜいmutexで済むのが救いだが)を使うしかありません。
それから、このような問題はある構造体のたった1つのmemberを読むだけでも起こり得ます。したがって、kernelのほぼ全てに渡って影響を及ぼします。そのような問題に対してmachine-dependentな対策をとった場合、特定のarchitectureでしか現れないbugをkernel全体にばらまいてしまう恐れがあります。
そういうわけで、FreeBSDではこの問題をmachine-independentなlock primitive(実際にはsleep mutex)で解決することにしました。これならsys/kern以下のlockに関わる問題をi386で解決すれば、sparc64でもその恩恵をそのまま受けることができます。
Re:新機能 (スコア:1)
i386では問題なかった -> 字面上の命令の順序は問題なかった -> それでsparcで問題がおきたということはストア命令が他のプロセッサから違う順番で見えた -> membar #Syncを入れると良い
というのでどこか間違ってるでしょうか?
まともなプロセッサなら強いordering(i386)かメモリバリア(こっちが多数派だし将来的に増えるハズ)のどっちかがあるはずなので特定のアーキテクチャに依存するということは無いと思います。
Re:新機能 (スコア:2)
*の部分ですが、問題が起きるのはC言語上では1つの文(たいていは式文)でありながら、assemblerに落とすと複数回のstoreを必要としてしまう場合です(2重以上の間接参照をdereferする場合など)。この場合はC言語ではそれ以上式を分割できないため、C言語のレベルでは解決できません(マクロなどは一切使えない)。
ではdereferenceを全てバラしてcompilerが頑張ればいいかというと、そうもいきません。一般にあるdataがthread-localであるか否かを自動的に判断するのは(特にpointerの値を簡単にいじることができ、かつそれが必要になる場面では)技術的に困難な問題を抱えてしまいます。かといって全てにmemory barrierを張ると、並列度が落ちて無駄にperformanceを悪化させる結果になります。ならばassemble listに手を加えて...というのは、すでに4.3BSDで失敗しています。
memory barrierはあくまで1つのinstructionだけに対して同期をとるための手法です(その点ではi386のlock prefixと変わらない)。したがって、test-and-setやconditional storeなどの命令と併用するぐらいしか有効な使い道はありません。
なお、上述の問題はinstruction setについてmemory accessを何回認めるかに対する考え方の違いが原因です。したがって、この問題は10年、20年、50年経っても解決を見る見込みはありません。とならば、いたずらに問題を複雑化させるよりも、より問題を(machine-independentにすることにより)発見しやすくしておく(より多くの人が再現実験に加われる)努力をすべきです。最適化はその後でも遅くありません。
Re:新機能 (スコア:1)
>>C言語上では1つの文(たいていは式文)でありながら、assemblerに落とすと複数回のstoreを必要としてしまう場合です(2重以上の間接参照をdereferする場合など)。この場合はC言語ではそれ以上式を分割できないため
の例を示していただけないでしょうか?
それと
>>memory barrierはあくまで1つのinstructionだけに対して同期をとるための手法
これはメモリバリアのどのような側面を指してそうおっしゃてるのでしょうか?
Re:新機能 (スコア:2)
n重参照のdereference(n>2)は、例えば
の左辺ですね。これはsignal処理の中で出てきた例(実際に問題になった)ですが、ほかにもprocess groupやsessionをprocessからたどる場合によく起こります。FreeBSDに関していえば、KSE(Kernel Scheduling Entity)のmergeにより、processももはや出発点ではなく、threadに貼りつくだけのものになってしまいました。ですから、
というdereferenceもぼちぼち出てきてます。まぁ、Cのレベルで複数の式文に分けることはできますが、実際にキーを打つ立場としてはそれをやると読みづらいし、あちこちいじらないといけないし、ローカル変数の初期化を忘れて...など、面倒なことの方が多いです(そんなことに時間を割く余裕はない)。
また、このような文を書いた場合、アドレス値のloadを複数回、しかも一般には不連続に(loadだけを連続実行することができない)繰り返すことになります。こうなるとmemory barrierだけではloadの間に入った別の命令を超えた保護ができません。
Re:新機能 (スコア:1)
>>C言語上では1つの文(たいていは式文)でありながら、assemblerに落とすと複数回のstoreを必要としてしまう場合です(2重以上の間接参照をdereferする場合など)。この場合はC言語ではそれ以上式を分割できないため
に対するもので、この場合storeはやってないように見えます。
それから
>>実際、i386では平気だと思っていたものがsparc64ではうまく動かず、lockのかけなおしをする羽目になった
と書かれていますが、このコードはi386ではロックなしで問題ないのでしょうか?
コンパイラの最適化 (スコア:1)
brake-handle さんのおしゃる通りなのですが 「問題が起きるのはC言語上では1つの文(たいていは式文)でありながら、assemblerに落とすと複数回のstoreを必要としてしまう場合」 以上に、 C コンパイラの最適化の掛かり方が 問題になることが多いと思います。
は2回の load に変換されるわけですが、 最適化によってこの2つの load 命令の距離が 引き離されて 間に他の load/store 命令が入ってくることが 考えられます。 こういう場合に、 メモリバリアを 関数なりインラインアセンブラの形で 挿入すると 最適化が切れて一見正しく実行されるコードが 出力さることがあります。
結局、 C 言語を使ってマルチスレッドプログラムをする場合、 「(machine-independentな)ワードの読み書きは アトミックに行われる」以上の同期は期待でき ないです。 アーキテクチャ/コンパイラの組み合わせによっては double 型や 64ビット整数の代入すら アトミックになりませんし。
コンタミは発見の母
Re:コンパイラの最適化 (スコア:1)
>>i386では平気だと思っていたものがsparc64ではうまく動かず、lockのかけなおしをする羽目になった経験があります。
なんてことがありうるのだろうかと興味があったのでダラダラと議論を長引かせてしまいました。上記の指摘された問題であればi386の方でもマズイですよね?doubleとか64bit整数だと逆にsparc64では大丈夫ってことになりそうですし。