fc2ブログ

並列処理システムの設計の勘所は「スレッドを使わない事」だ

 当ブログのスレッド数決定問題にて、並列処理システム設計をする上でスレッドを決定する事の難しさと大切さを説きました。その中で既に言及していますが、重要なので強調した記事を書きます。
 システム設計に於いて、リソースの使用は大事な検討課題です。具体的には、リソース対象を特定し、そのリソースが何byteのデータか、そして権限はどうするのかまで考えなくてはなりません。そうしないと、ネットワーク設計・データベース設計・セキュリティ設計は出来ません。データ量が分からずとして、システムの拡張性と安定性は確保できませんし、使用するリソースと権限が分からずとしてセキュリティ対策は出来ません。となれば、同様の理由でデータベース設計も出来ません。
 並列システムの設計では熟考するべきリソースは、現状のOSを考えると「スレッド数」と「CPUのコア数」です。OSの設計思想が変わり、スレッドモデル以外が選択されれば、もちろんその何かになります。それに関連して、データベース設計の視点から見ると、リクエスト数の内容が関係してきます。つまり、ハードウェアリソースと、それに対応付けられているソフトウェアリソースは重要なのです。
 スレッド数の決定とくれば、多くの人は使用する事ばかりを考えてしまいます。しかしながら、リソースを使用する事ばかりを考えると、ハードウェアがそれに追いつきません。コア数が32個あっても足らず、64個、128個、256個...と「もっとコアを!」状態になるのは目に見えています。何故ならば、既に現状でスレッドを使い過ぎているからです。
 タスクマネージャを見てみましょう。貴方のPCでどれだけのスレッド数が要求されているでしょうか?確認すれば32個以上のスレッドを使っているのが分かると思います。それを踏まえずとして、「このシステムで使うアプリケーションは、コア数を最大限に使用しよう」などととんでもない設計をすれば、アプリケーション数 * コア数となり、ハードウェアリソースが永遠に不足する酷いシステムが出来上がります。
 とはいえ、「スレッドを使わないために絶対に並列処理をしない」などというのは馬鹿げた極論です。この様なシステム方針にしてしまうと、ハードウェアを増強したら処理が速くなると考えているエンドユーザーの期待を裏切ってしまいます。これはあってはならない事です。
 相反する事を書いているように見えるかもしれませんが、当たり前の一つの真実を言っています。それは、リソースを考えて使用する事の大切さです。あればあるだけリソースを使いきるのは愚かな行為ですし、だからと言ってリソースを使わないのもまた愚かな行為です。リソースは、必要な時に必要なだけ使用しなくてはなりません。すなわち、リソースを使用する判断と、リソースを使わない判断もせねばならないのです。
 最近は潤沢なハードウェアリソースと、便利な開発ツールを活かした富豪プログラミングと富豪設計が行われている節がありますが、どのような資源も無限ではありません。私達技術者はリソースのコントロールが求められています。今はまだ表面化していないかもしれませんが、電機事情が複雑になってきた時代背景を鑑みると、これからの時代はリソースのコントロールが当たり前の要求となるのは目に見えています。
 私達は昔では考えられなかった、潤沢なハードウェアリソースとソフトウェアリソースを手にしています。しかし、それら豊富なリソースは有限であり、リソースを意識せずにシステム設計および実装をすると、何時か化けの皮がはがれます。従って、技術者は常にリソースのコントロールが求められていると考えるのが妥当です。プロフェッショナルらしく、リソースを巧みに使用する技術者を一緒に目指しましょう。
 そうすれば私達情報技術者は、尊敬のまなざしを受ける職業になるでしょう。
スポンサーサイト



テーマ : プログラミング
ジャンル : コンピュータ

スレッド数決定問題16

 この記事はスレッド数決定問題15の続きです。前回は、並列処理システム設計技法の概要を解説しました。今回は、順序的な依存性と並列性について解説します。
 あらゆる処理には前提と順序が存在します。並列処理システムの設計に不慣れな人は、順序があるから並列化出来ないと考えてしまいます。しかし、どんな処理でも順序があるのにも関わらず、現実には並列化されている処理は色々あります。もし順序があれば並列処理が出来ないのであれば、あらゆる処理は並列化出来ない事になります。従って、見方を変えれば並列化できると結論付けられます。
 具体的には、情報の抽象度を変える事により処理を並列化できます。例えば、厳密な順序が決まっている処理Aがあるとします。この処理Aだけを見れば並列化できないかもしれません。しかしながら、処理Aを包含する処理Bに視点を移せば話しは変わってきます。処理B内で処理Aを複数同時実行できるかもしれません。
 この例から分かると思いますが、並列処理化の対象はできるだけ抽象度が高い処理にします。インテル社のCPUが良い例です。プロセッサ内の処理をユニットに分け、パイプライン処理などの高度な並列処理をしています。つまり、抽象度が高いオブジェクトを定義しておけば、内部の処理を並列化する事が可能となるという事です。
 総括します。システムを並列化するには、従来の直列的なアルゴリズムの発想で設計してはなりません。並列特有の問題点を知り、今までとは違う視点でシステムを設計せねばなりません。もちろんこれは分析段階にも言えます。システムのどの部分を並列化するのかを決めるには、並列処理で必要となる情報を収集せねばなりません。これらの事柄を面倒に感じる人がいるでしょう。
 しかしながら、現在に於いて並列処理は必要不可欠な技術であり、その効果も高いので避けては通れません。並列処理はパフォーマンスを向上させますが、システムの構成も変化するので、新しい発想のシステムが実現できます。苦労は多いですが、その分見返りも大きいのです。並列処理を学習し、お客様が喜ぶシステムを構築しましょう。

テーマ : 情報処理技術
ジャンル : コンピュータ

.NET並行処理プログラミング入門8

 この記事は.NET並行処理プログラミング入門7の続きです。今回も、実行するスレッドを切り替える機能を解説します。
 前回のサンプルプログラムの内容は、重要度が低いAの処理よりも、重要度が高いスレッドBの処理を先に終わらせるというものです。このサンプルのキーは、Threadクラスの静的メソッドYieldです。
 Yield静的メソッドを使用すると、他のスレッドが実行する機会を与えるようOSに指示を出します。しかし、必ず他のスレッドが実行できるとは限りません。なんらかの理由でOSが他のスレッドを実行できなかった場合false(偽)を返します。たとえば、他に実行可能なスレッドがない場合falseが返されます。
 前回のサンプルプログラムで、Yield静的メソッドの戻り値をチェックしていたのはこのためです。また、trueを返した場合も、どのスレッドが実行されたのかは、工夫しないと分からない事を考慮せねばなりません。あくまでもYield静的メソッドはOSに対して、他のスレッドを実行するように指示するだけなのです。
 数回に渡ってSleepメソッドとYieldメソッドを解説しました。この2つのメソッドを知れば、並行処理プログラミングの世界が少し見えてきます。ただし、この2つのメソッドは多用してはなりません。奥の手として使用して下さい。何故ならば、この2つのメソッドが必要な時は、大概アルゴリズムそのものが間違っているからです。設計が間違っていなければ、この2つのメソッドは必要ない筈です。
 とはいえ、特殊な状況下では必要となります。また、この2つのメソッドを使用すれば、スレッドをコントロールする事が出来ますので、並行処理のテスト時には大きな力となります。地味ですが、背景知識とともに覚えておくべきメソッドと言えます。

テーマ : プログラミング
ジャンル : コンピュータ

.NET並行処理プログラミング入門7

 この記事は.NET並行処理プログラミング入門6の続きです。前回は、スレッドの処理を一時中断する機能について解説しました。今回は、実行するスレッドを切り替える機能を解説します。
 並行処理プログラミングをしていると、別のスレッドの処理を実行したい場面に遭遇します。たとえば、重要でないが計算量が少ないもののアプリケーションが終了するまで実行するスレッドAの処理と、有限で重要だが処理量が多いスレッドBの処理を並行処理していると仮定します。
 この場合、スレッドAの処理ばかり実行されてしまい、重要なスレッドBの処理終了が遅くなる可能性があります。この問題を解決するには、スレッドAの処理を中断し、スレッドBの処理を優先的に実行する必要があります
 幸いThreadクラスには、別のスレッドの処理を実行する為に、実行するスレッドを切り替える機能があります。早速その方法を見てみましょう。

using System;
using System.Threading;

class YieldSample
{
    //Bスレッドが処理を終えた場合true
    static bool isComplete = false;

    static void Main( string[] args )
    {
        Thread a = new Thread( new ThreadStart( AThreadMethod ) );
        Thread b = new Thread( new ThreadStart( BThreadMethod ) );
        a.Start();
        b.Start();
        a.Join();
        b.Join();
    }

    //あまり重要でない処理
    static void AThreadMethod()
    {
        //Bスレッドが実行されるまで待つ
        while ( Thread.Yield() == false | isComplete == false );
        Console.WriteLine( "スレッドAの処理が終了しました。" );
    }

    //絶対先に終了させたい処理
    static void BThreadMethod()
    {
        Console.WriteLine("スレッドBの処理が終了しました。");
        isComplete = true;
    }
}

長くなったので次回解説します。

テーマ : プログラミング
ジャンル : コンピュータ

.NET並行処理プログラミング入門6

 この記事は、.NET並行処理プログラミング入門5の続きです。引き続きThreadクラスが持つ機能とスレッドの概念について解説します。
 早速ですが新しいスレッドの機能を紹介します。ひとまずサンプルを見て下さい。

using System;
using System.Threading;

class TimeStop
{
    static void Main( string[] args )
    {
        //約3000ミリ秒(3秒)間メインスレッドを止める
        Console.WriteLine( "時が止まる。" );
        Thread.Sleep( 3000 );
        Console.WriteLine( "そして動き出す。" );
    }
}

このサンプルコードを実行すると、まるで時が止まったかのようにプログラムが約3秒間停止し、その後メッセージを出力して終了します。メインスレッドの動きを止めたのはThread.Sleep静的メソッドです。
 Sleep静的メソッドの引数にはミリ秒単位の値を指定して実行します。Sleep静的メソッドを実行すると、引数で指定した値に等しいミリ秒間、実行したスレッドの動きを止めます。ここで注意してほしい事は、Sleep静的メソッドは正確な時間を保証できない事です。あくまでも指定ミリ秒間、実行したスレッドの動きを止めるだけです。
 正確な時間を保証できない理由は、WindowsOSがリアルタイムOSではないからです。.NET FrameworkはOS上で動作していますので、リアルタイムな動作を保証しないOS上では正確に時間を管理できません。将来リアルタイムOSの上で動作する.NET Frameworkが登場した際には、正確な時間が期待できるかもしれませんが、ひとまず正確な時間を指定する事は不可能だと考えて下さい。続く...
 

テーマ : プログラミング
ジャンル : コンピュータ

.NET並行処理プログラミング入門5

 この記事は、.NET並行処理プログラミング入門4の続きです。引き続きThreadクラスが持つ機能とスレッドの概念について解説します。
 早速ですが、前回提示した問題があるサンプルを改良したものを掲載し、それを元に解説します。

using System;
using System.Threading;

class ThreadSample
{
    static void Main( string[] args )
    {
        //専用のスレッドで計算をする
        AdditionMan addMan = new AdditionMan();
        ParameterizedThreadStart addStart =
            new ParameterizedThreadStart( addMan.Calculation );
        Thread addThread = new Thread( addStart );
        int maxValue = 10;
        addThread.Start( maxValue );
        addThread.Join(); //処理の流れを合流する

        //計算結果を表示
        Console.WriteLine( "1 ~ {0} までの数を足すと{1}になります。",
            maxValue, addMan.Sum );
    }
}

class AdditionMan
{
    private long m_sum;
    public long Sum { get { return this.m_sum; } }

    public void Calculation( object value )
    {
        int max = ( int ) value;
        for ( int i = 1; i <= max; i++ ) this.m_sum += i;
    }
}

前回との違いは緑色で表示したコードだけです。ThreadクラスのJoinメソッドを呼び出す事により、前回のコードにあった不備を解決できます。
 Joinメソッドは呼びだし元のスレッドを、ブロックさせる効果があります。このサンプルの場合、Joinメソッドを呼び出したメインスレッドの動きを止め、新しく作成したスレッドの処理が終了した後再開します。Joinメソッドを呼び出さないと、メインスレッドは計算処理を待たずに自身の処理を進行し、計算処理が終わる前に終了してしまいます。それで前回のサンプルは、計算結果が0になってしまうのです。この処理の流れを並行処理プログラミング初心者は分かり難いと思います。並行処理プログラミングに慣れる為に、処理の流れが合流するとイメージするとよいでしょう。そうすれば簡単に感じます。
 Joinメソッドが合流するイメージである理由は、スレッドは処理の流れとイメージするとよいからです。Thread(スレッド)という単語は、「糸、細い流れ、話の筋、全体を一つにつなぐ特徴」などを意味するので、処理が流れる様子をイメージするとしっくりきます。
 この様にスレッドをイメージし、メインスレッドの処理の流れと、計算専用の処理が別に流れる様をイメージすると、並行処理プログラミングが分かりやすくなります。

テーマ : プログラミング
ジャンル : コンピュータ

.NET並行処理プログラミング入門4

 この記事は.NET並行処理プログラミング入門3の続きです。前回は、スレッドの種類と複数のスレッドの実行について解説しました。今回はThreadクラスが持つ機能とスレッドの概念について解説します。
 スレッドを扱えるようになると、特定の処理を専用のスレッドで実行したくなります。特定の処理を他のスレッドに任せれば、メインスレッドは処理を続けられるので、同時に2つの処理が出来るようになり非常に便利です。
 簡単な加算処理を他のスレッドに任せるプログラムのサンプルを元に、この事について考えてみます。

using System;
using System.Threading;

class ThreadSample
{
    static void Main( string[] args )
    {
        //専用のスレッドで計算をする
        AdditionMan addMan = new AdditionMan();
        ParameterizedThreadStart addStart =
            new ParameterizedThreadStart( addMan.Calculation );
        Thread addThread = new Thread( addStart );
        int maxValue = 10;
        addThread.Start( maxValue );

        //計算結果を表示
        Console.WriteLine( "1 ~ {0} までの数を足すと{1}になります。",
            maxValue, addMan.Sum );
    }
}

class AdditionMan
{
    private long m_sum;
    public long Sum { get { return this.m_sum; } }

    public void Calculation( object value )
    {
        int max = ( int ) value;
        for ( int i = 1; i <= max; i++ ) this.m_sum += i;
    }
}

このサンプルが行っている事は実に簡単です。スレッドを作成し、1~10までの数を合計する処理を、作成したスレッドで実行しているだけです。
 注目するべき所はParameterizedThreadStartデリゲートを使用している点と、ThreadオブジェクトのStartメソッドに値を渡している点です。ParameterizedThreadStartデリゲートを使用してThreadのコンストラクタを呼び出すと、スレッドの処理開始時(Startメソッド呼び出し時)に値を渡せるようになります。ただし、デリゲートで指定するメソッドは、Object型の引数を1つ受け取るものでなくてはなりません。注意して下さい。
 このサンプルを実行すると合計値は何になると思いますか?多くの人は55と答えると思います。しかし、実際に実行してみると違う結果を表示します。
※55と表示される場合はもっと大きな数を指定して下さい。
 その理由と対策について次回解説します。

テーマ : プログラミング
ジャンル : コンピュータ

.NET並行処理プログラミング入門3

 この記事は.NET並行処理プログラミング入門2の続きです。前回はスレッドの生成方法および実行方法を解説しました。今回はスレッドの種類と複数のスレッドの実行について解説します。
 前回のサンプルは並行処理をしている実感が得られなかったと思います。そこで、今回は2つのスレッドを実行するサンプルを掲載し、スレッドオブジェクトについての解説を進めます。


using System;
using System.Threading;

class ThreadSample
{
    static void Main( string[] args )
    {
        //カウントスレッドを用意
        ThreadStart start = new ThreadStart( Piyo.Count );
        Thread counter = new Thread( start );

        //ピヨスレッドを用意
        Piyo p = new Piyo();
        ThreadStart piyoStart = new ThreadStart( p.PiyoOut );
        Thread piyopiyo = new Thread( piyoStart );
        piyopiyo.IsBackground = true;

        //二つのスレッドを実行
        counter.Start();
        piyopiyo.Start();
    }
}

class Piyo
{
    public Piyo() { }
    public void PiyoOut()
    {
        while( true ) {
            Console.WriteLine(" ピヨ ");
        }
    }

    public static void Count()
    {
        Console.WriteLine( "数えるピヨ♪" );
        for ( long i = 0; i < 1000; ++i ) {
            Console.Write( "{0} ", i );
        }
        Console.WriteLine();
    }
}

このサンプルは一見すると、ピヨスレッドの処理が終わらないので、永遠に処理が続くように見えます。しかし、実際はちゃんと終了します。その理由は、バックグラウンドスレッドが他の種類のスレッドに強制終了させられるからです。
 非並行処理の.NETのプログラムが動いているのは、メインスレッドが動作しているからです。そして、サンプルのカウントスレッドのようなフォアグラウンドスレッドが動いている間プログラムは終了しません。フォアグラウンドスレッドは、全ての処理が終了すると、全てのバックグラウンドスレッドを停止しプログラムを終了させます。
 フォアグラウンドスレッドとバックグラウンドスレッドの違いは重要なので絶対に覚えて下さい。どういう観点で使い分けるのかの目安を言います。バックグラウンドスレッドは途中で終了しても支障がないサブ処理で使用します。一方、フォアグラウンドスレッドは、途中で終了すると不都合がある処理で使用します。
注意:これはあくまでも目安なので、実務で使用する前にこの連載の続きやMSDNをよく読んで下さい。
 バックグラウンドスレッドは、処理の途中で強制的に終了させられるので十分に注意して使用して下さい。バックグラウンドスレッドで処理をする場合は、いきなり処理が終了させられる可能性があるので扱うデータの整合性を保てるように工夫しましょう。続く...

テーマ : プログラミング
ジャンル : コンピュータ

.NET並行処理プログラミング入門2

 この記事は.NET並行処理プログラミング入門1の続きです。前回は.NETにおけるスレッドモデルについて解説します。今回はスレッドの生成方法および実行方法を解説します。
 何はともあれ、先ずはスレッドを生成して実行してみましょう。スレッドの生成方法と、生成したスレッドの実行方法をサンプルで示します。

using System;
using System.Threading;

class ThreadSample
{
    static void Main( string[] args )
    {
        ThreadStart start = new ThreadStart( Piyo.Count );
        Thread counter = new Thread( start );
        counter.Start();
    }
}

class Piyo
{
    public static void Count()
    {
        Console.WriteLine("数えるピヨ♪");
        for ( long i = 0; i < 100; ++i ) {
            Console.Write( "{0} ", i );
        }
        Console.WriteLine();
    }
}

サンプルを見て、スレッドの生成および実行が意外と簡単な事に驚いた人もいるかと思います。スレッドモデルによる並行処理プログラミングの概念は難しいもののコーディングは簡単です。
 .NETのSystem.Threading.Threadオブジェクトは、System.Threading.ThreadStartデリゲートを引数として受け取るコンストラクタを呼び出す事によりインスタンスを生成します。他にもコンストラクタがあるのですが、ひとまずこの方法を覚えて下さい。
 Threadオブジェクトのインスタンス取得後は、Startメソッドを呼び出すだけで実行できます。これで.NET並行処理プログラミングの第一歩を踏み出した事になります。色々気になる事があるかと思いますが、長くなるので今回は終わります。
 次回へ続く...

テーマ : プログラミング
ジャンル : コンピュータ

.NET並行処理プログラミング入門1

 この記事は、.NET並行処理プログラミング入門の続きです。前回は並行処理に関する基礎的事柄を解説しました。今回は.NETにおけるスレッドモデルについて解説します。
 .NET Frameworkでのプログラミングは実行環境を提供しており、Win32を使ったネイティブなプログラミングとは異なります。.NET Frameworkにおける並行処理実行環境を知るところから始めるのがベストです。そこで、先ずはWin32のスレッドモデルをおさらいし、次に.NET Frameworkのスレッドモデルを解説します。両方のスレッドモデルを理解する事により、並行処理の理解が深まり、スレッドを自由自在に操れるようになります。
 Windowsが管理しているネイティブなスレッドはプロセス内に存在します。Windowsはプロセス内に、共有リソースと1つ以上のスレッドを保持します。こうする事により、バグを抱えたプログラムの影響を限定化する事が出来ます。もし仮にプロセス内ではなく、全スレッドが同一空間に管理されていると、一つのスレッドの過ちがOS全体に影響を与えてしまいます。プロセス内のプログラムは通常他のプロセスのプログラムにアクセスできないのでその心配がなくなります。
 一方.NET Frameworkでは、プロセス内に1つ以上のアプリケーションドメインを持ちます。そして、アプリケーションドメイン内で共有リソースとスレッドを保持しています。一見複雑化しただけですがこの方式には利点があります。
 アプリケーションドメイン内でスレッドを保持する事により、さらにバグの影響範囲を限定し、プログラムがより一層堅牢になります。それに加えて、アプリケーションドメインごとにセキュリティ等の構成を設定でき、アセンブリのロード&アンロードも行えます。アプリケーションドメインという概念があるお陰で、プログラムの構成がさらに堅牢かつ柔軟になると言えます。
 先ほどWindowsが管理するスレッドをネイティブなスレッドと表現しました。この理由は、.NET FrameworkのスレッドがOSが管理するスレッドと一対一で対応しなくなる可能性があるからです。.NET Frameworkは今のところ.NETのスレッド=Windowsのスレッドですが、マイクロソフト社は将来のバージョンでパフォーマンスやセキュリティ上の理由で.NETのスレッドを抽象化するかもしれません。これは重要ですので覚えて下さい。
 覚えるべき事はまだまだ沢山ありますが、一度に沢山解説しても退屈なだけなので今回はひとまず終わりにします。次回からサンプルを交えつつ、.NET並行処理プログラミングの解説を進めます。続く...

テーマ : プログラミング
ジャンル : コンピュータ

プロフィール

インドリ

Author:インドリ
みなさん、はじめまして、
コンニチハ。

ボクは、無限の夢(infinity dream)を持つネタ好きな虹色の鳥インドリ(in dre)です。
色々な情報処理技術を啄ばむから楽しみにしてね。

http://twitter.com/indori
は別人による嫌がらせ行為です。
私とは関係ないので注意して下さい。
次はなりすましブログなどをするかもしれませんが、ここ以外でブログをするつもりがないので、ここ以外にインドリのブログがあったとしても無視してください。


何度言っても分からない人がいるので、ここにコメント欄へ書き込むときの注意事項を書きます。


一、社会人としてのマナーをわきまえましょう。
一、妄想に基づく書き込みを止めてください。
一、暴言の類は書かないで下さい。
一、某誹謗中傷サイトの書き込みは彼らの妄想に基づく書き込みですから無視して、ここへ書き込まないで下さい。
一、コメント書く前に他のコメントよく読んでから行って下さい。
一、言いがかかり等の行為を禁止します。
一、その他常識的に考えて迷惑なコメントはしないで下さい。


以上のルールを守れない人のコメントは削除します。



利用上の注意
ここに紹介してある文章およびプログラムコードは正確であるように心がけておりますが、内容を保証するものではありません。当サイトの内容によって生じた損害については、一切の責任を負いませんので御了承ください。


執筆したCodeZineの記事


【VB.NETで仮想CPUを作ろう】

  1. VB.NETで仮想CPUを作ろう
  2. レジスタの実装
  3. 仮想CPUのGUI化
  4. テストドライバの改良
  5. CPUの基礎動作の実装
  6. MOV命令の実装
  7. ADD命令実装
  8. SUB命令実装
  9. INC命令&DEC命令の実装と命令長
  10. MLU命令の実装とModR/Mについて
  11. DIV命令の実装とイベント設計について
  12. 機械語駆動式 関数電卓を作ろう!
  13. 機械語駆動式 関数電卓を作ろう! 解答編(前半)
  14. 機械語駆動式 関数電卓を作ろう! 解答編(後半)


【仮想ネットワーク実装でTCP/IPを学ぼう】
  1. TCP/IPの基礎と勘所
  2. ネットワークアクセス層の勘所
  3. インターネット層の勘所
  4. トランスポート層の勘所
  5. アプリケーション層の勘所
  6. セキュリティの基礎と仮想ネットワークの仕様
  7. GDI+と独自プロトコルの定義



【並列化】
インテル Parallel Studioを使って並列化プログラミングを試してみた
並列プログラミングの効率的なデバッグを実現する「Parallel Inspector」


【TBBシリーズ】
  1. インテル スレッディング・ビルディング・ブロックの概要
  2. インテルTBBから学ぶループの並列化
  3. スレッドセーフとインテルTBBのコンテナ
  4. インテルTBBのスレッドクラス


【OpenMPシリーズ】
  1. OpenMPの基礎構文
  2. OpenMPの実行時ライブラリと並列ループ
  3. OpenMPのメモリモデルとfork- joinモデル

最近の記事
最近のコメント
月別アーカイブ
カテゴリ
Ada (9)
COBOL (5)
C (9)
C++ (11)
C# (370)
D (25)
Java (8)
Perl (1)
Ruby (14)
PHP (2)
Boo (2)
Cobra (2)
LISP (6)
F# (33)
HTML (0)
XHTML (0)
CSS (0)
XML (0)
XSLT (0)
Scala (4)
WPF (0)
WF (2)
WCF (0)
LINQ (4)
MONO (5)
Linux (0)
MySQL (0)
ブログ内検索
リンク
最近のトラックバック
RSSフィード
ブロとも申請フォーム

この人とブロともになる

QRコード
FC2カウンター