fc2ブログ

Win32並行処理プログラミング入門11

 この記事は、Win32並行処理プログラミング入門10の続きです。前回は、グローバル変数の危険性について書きました。今回は、クラスのメンバー変数の危険性について書きます。
 並行処理プログラミングに於いて、グローバル変数だけが問題を起こすのではありません。グローバル変数を使用しなくとも、リソースを無防備に共有すれば問題が発生します。その事を示すために、複数のスレッドがメンバー変数を書き変えるメソッドを実行するサンプルを用意しました。

#include <iostream>
#include <windows.h>
#include <tchar.h>
#include <process.h>
using namespace std;

//#define ATOMIC //アトミック関数の使用有無
const int threadCount = 64;

class InstanceAndParameter
{
private:
    void* ins;
    void* param;
public:
    InstanceAndParameter( void* ins, void* param ) 
        : ins( ins ), param( param ){}
    void* getInstance() const { return ins; } 
    void* getParameter() const { return param; }
};

class Foo
{
private:
    long number;
public:
    Foo() : number(0) {}
    long getNumber() const { return number; }

    //並列的に実行するメソッド
    void AddFunc( int count ) 
    {
        //アトミックな関数を使用すると正常に加算される
    #ifdef ATOMIC
        for ( int i = 0; i < count; i++ ) 
            InterlockedExchangeAdd( &number, 1 );
    #else
        for ( int i = 0; i < count; i++ ) number++;
    #endif
    }
};

//スレッドから呼び出されるメソッド
static unsigned __stdcall FooCallAddFunc( void* pvParam ) 
{
    //パラメータのチェック
    _ASSERTE( FALSE == IsBadReadPtr( pvParam, 
            sizeof( InstanceAndParameter ) ) 
        && "スレッドに渡されたパラメータが無効です" ); 

    //インスタンスとパラメータを取り出してメソッドを実行
    InstanceAndParameter* ip = 
        reinterpret_cast< InstanceAndParameter* >( pvParam );
    Foo* obj = reinterpret_cast< Foo* >( ip->getInstance() );
    int count = PtrToInt( 
        reinterpret_cast< INT_PTR >( ip->getParameter() ) );
    obj->AddFunc( count );
    return 0;
}

int _tmain( int, _TCHAR* )
{
    //スレッド数の判定
    if ( threadCount > MAXIMUM_WAIT_OBJECTS ) {
        cout << "【エラー】" << endl;
        cout << "指定するスレッド数が多すぎます。" << endl;
        cout << "指定するスレッド数は" 
            << MAXIMUM_WAIT_OBJECTS 
            << "以下にして下さい。" << endl;
        return -1;
    }

    //スレッドのパラメータを用意する
    Foo obj;
    int count = 100000;
    InstanceAndParameter threadparam( 
        reinterpret_cast< void * >( &obj ), 
        reinterpret_cast< void * >( ( INT_PTR ) count ) );

    //スレッドを作成する
    HANDLE hThreads[ threadCount ];
    for ( int i = 0; i < threadCount; i++ )
    {
        hThreads[ i ] = reinterpret_cast< HANDLE >( 
            _beginthreadex ( 
                __nullptr,
                0U,
                FooCallAddFunc,
                reinterpret_cast< void * >( &threadparam ) ,
                CREATE_SUSPENDED, //直ぐには実行しない
                __nullptr ) );
    }

    //作成したスレッドを実行
    for ( int i = 0; i < threadCount; i++) 
        ResumeThread( hThreads[ i ] );

    //タイムアウト時間をミリ単位で指定して待機
    //※指定した時間は正確ではありません
    DWORD result = WaitForMultipleObjects( 
        threadCount, hThreads, TRUE, 2000 );

    //WaitForSingleObject関数が終了した原因を表示
    cout << "【スレッドの状態を表示します】" << endl;
    unsigned int max = ( WAIT_OBJECT_0 + threadCount - 1 );
    if ( result == WAIT_FAILED ) { 
        //エラーを表示する
        LPVOID title = _T( "エラー" );
        LPVOID msg;
        FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER |
                FORMAT_MESSAGE_FROM_SYSTEM |
                FORMAT_MESSAGE_IGNORE_INSERTS,
            __nullptr,
            GetLastError(),
            MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ), // 既定の言語
            reinterpret_cast< LPTSTR >( &msg ),
            0,
            __nullptr
        );
        MessageBox( __nullptr, 
            reinterpret_cast< LPCTSTR >( msg ) , 
            reinterpret_cast< LPCTSTR >( title ), 
            MB_OK | MB_ICONERROR );
        LocalFree( msg );
        return -1;
    } 
    if ( result == WAIT_TIMEOUT ) {
        cout << "タイムアウトしてしまいました。" << endl;
    } else if ( ( result >= WAIT_OBJECT_0 ) & ( result < max ) ) {
        cout << "全スレッドの処理が終わりました。" << endl;
    } 
    cout << endl;

    //グローバル変数の合計値を表示
    long correctValue = threadCount * count;
    long number = obj.getNumber();
    cout << "【グローバル変数の値を表示します】" << endl;
    cout << "予想値:" << correctValue << endl;  
    cout << "実際の値:" << number << endl;
    cout << "不足値:" << ( correctValue - number ) << endl;

    //ハンドルを閉じる
    for ( int i = 0; i < threadCount; i++ ) 
        CloseHandle( hThreads[ i ] );
    cout << endl;
    return 0;
}

このサンプルも、アトミック関数を使用しないと正常に動作しません。理由は、並行的にメンバー変数を書き変えているからです。共有リソースを複数のスレッドが操作すると、グローバル変数が危険なのとほぼ同じ理由で問題が発生します。続く...
スポンサーサイト



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

Scalaにおけるシングルトンオブジェクトの罠

 Scalaのシングルトンオブジェクトの使用は警戒せねばなりません。シングルトンオブジェクトと言うぐらいだから、絶対に1つしか作成されないかというとそうでもないようです。

class Sample
{
  private object Inner {
    private var value : Int = 0
    def getValue = value
    def addValue = { value += 1 }
  }
  def addValue = Inner.addValue
  def getValue = Inner.getValue
}

object Main {
  def main(args: Array[String]): Unit = {

    //静的に値がカウントされているのかを実験
    val obj = new Sample
    obj.addValue
    printf( "オブジェクト1の値:%d\n", obj.getValue )

    val obj1 = new Sample
    obj1.addValue
    printf( "オブジェクト2の値:%d\n", obj1.getValue )
  }
}

※NetBeansにて試しました。
このサンプルを実行すると予想に反して、オブジェクト1と、オブジェクト2の値が共に1になってしまいます。シングルトンオブジェクトなのにこれは変です。これでは、内部オブジェクトにして、静的変数を模倣できません。
 その答えは、Scalaの実装方式にあるようです。Scalaは自動生成クラスのインスタンスとして、シングルトンオブジェクトを実装しています。ですから、インナークラスの値が毎回初期化されているように見えるのです。私はてっきり、次の様なJavaプログラムと等価になると思っていました。

//静的内部クラス
class Sample
{
    private static class Inner {
        private static int value = 0;
        static int getValue() {  return value; }
        static void addValue() { value += 1; }
    }
    void addValue() { Inner.addValue(); }
    int getValue() { return Inner.getValue(); }
}

public class Main {
    public static void main( String[] args ) {

       //静的内部クラスを検証
       Sample obj = new Sample();
       obj.addValue();
       System.out.printf("オブジェクト1の値:%d\n", obj.getValue() );
       
       Sample obj1 = new Sample();
       obj1.addValue();
       System.out.printf("オブジェクト2の値:%d\n", obj1.getValue() );
    }
}

どうやら、内部オブジェクトに定義して、クラス数の増加を防ぐ方法は採れないようです。とはいえ、これは明らかにおかしな現象だから、後で直されるかもしれません。

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

Scalaなシングルトンオブジェクトを安易に定義してはならない

 先ほど、Scalaのシングルトンオブジェクトについて書いたので、注意事項を書きます。Scalaでは、シングルトンオブジェクトが簡単に記述できます。ですから、ついついシングルトンオブジェクトを多用しがちです。しかし、安易にシングルトンオブジェクトとして定義してはなりません。
 プログラマが知るべき97のことにて、サム・サーリスト氏が「シングルトンパターンの誘惑に負けない」と警告しています。これは真実です。オブジェクト指向設計をしていると、「これは単一のオブジェクトでは?」と思う事が沢山あります。しかし、開発を進めるに従って、情報が足りないだけであったと判明した場合や、仕様の変更に従ってシングルトンから普通のオブジェクトに変更される場合が多々ありました。
 Scalaでは容易に定義できる事もあり、シングルトンオブジェクトを使いたくなるでしょうが、慎重に設計および実装をしましょう。これは、他言語の静的クラスにも当てはまります。道具選びはくれぐれも慎重に行って下さい。便利な機能があるから使うのではなく、必然性がある時のみ機能を使いましょう。

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

C++/CLIで拡張メソッドが扱えない件

 突然ですが、C++/CLIでは拡張メソッドが扱えません。これは、LINQプログラミングをする上で非常に不利です。拡張メソッドは、System::Runtime::CompilerServices::Extension属性を使用する事を知っていれば、VB.NETと同様に拡張メソッドを扱えないか試す事でしょう。ですが、それは叶いません。その理由を考えるには、属性について考えないとなりません。
 そもそも、属性とは何でしょうか?属性の概念は、COMの契約記述形式を拡張できないという問題点が露呈した時に誕生しました。具体的に言いますと、1990年代前半にMTSで実現されました。トランザクションのように、横断的関心事を記述するにはアスペクトが定義できなくてはなりません。そこで、アスペクトを定義する技術が生み出されたのです。
 ここに問題の答えがあります。C++/CLIでref classのメソッドにSystem::Runtime::CompilerServices::Extension属性を適用する事は出来ますが、コンパイラがその情報を活用しなければ意味がありません。すなわち、属性はメタ情報を記述する為の手段であり、それだけでは何も実現しないのです。
 ある言語が他の言語にある機能をサポートしていない時、その背景を考える事により技術力を高められます。「C++/CLIには拡張メソッドがない」と騒ぐだけに終わらず、何故実現できないのかまで考える事をお勧めします。背景を考える行為は良い鍛錬になります。鍛練のチャンスを見逃さずに活かしましょう!

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

Scalaのシングルトンオブジェクトとクラスから考える言語設計

 私がScalaに触れて最初に驚いたの事は、クラスに静的メンバーを持てない事です。仕様書を調べるとstaticキーワードすら予約語にありません。では、静的情報はどう扱うのかというと、シングルトンオブジェクトで実現します。知らない人のために簡単なサンプルを掲載します。

object Main {
  def main( args: Array[String] ): Unit = {
    println( "Hello, Scala!" )
  }
}

これはいわゆるHello,Worldプログラムです。キーワードがclassではなく、objectである点に注目して下さい。クラスは静的メンバーを持てないので、シングルトンオブジェクトにエントリポイントを用意します。
 Scalaの言語設計は非常に大胆です。C++、C#、Java、VB.NETといった言語は静的メンバーを持てますので、インスタンス変数と静的変数が混在する事になります。この言語設計では、オブジェクト指向設計から見ると、静的と一時的の二つの側面を持つオブジェクトを、一つのクラスで実装する事になります。恐らく、Scalaの設計者はそれを嫌って、クラスに静的メンバーを持たせない事を決定したのでしょう。
 私はこのScalaの言語仕様に感銘を受けました。ここまで理論を徹底させるのは素晴らしい事です。ですがその一方で、クラスの数が増える事を意味するのではないかという懸念を抱きました。そこで、例を挙げつつ考察してみました。
 例として、静的情報が必要なFooクラスを考えてみます。しかし、Scalaは静的変数が持てません。これを素直に受け取れば、StaticFooクラスが必要となります。これでは、2つのクラスが出来てしまいます。大規模開発では、クラス数が増える事は馬鹿に出来ない問題です。では、どうすればいいのかと言いますと、内部クラスを定義すればいいのです。そして、シングルトンオブジェクの静的情報を操作するメンバーを公開すれば、認識可能なクラスの数は増えません。Scalaは非常に上手く設計されています。
※注意:理論的には正しいのですが、試してみたところ上手くいきませんでした。
 コンパイラは結局のところ、アセンブラを生成する道具です。しかし、設計思想を持つ事により、バイナリを生み出すだけの道具にはなりません。人間の思考を助ける道具にもなりえるのです。これは、情報処理のあり方そのものではないでしょうか?情報システムは、ただ仕事を処理するのではなく、新しいアイデアを生み出せるものでなければなりません。

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

実践的オブジェクト指向分析入門9

 この記事は、実践的オブジェクト指向分析入門8の続きです。前回は、業務手順と既存システム(これ以降既存業務システムと表記)の分析を行う理由について書きました。今回は、オブジェクト指向分析が誕生する前の方法論や技法を復習します。
 オブジェクト指向分析は新しい分析技法ではありません。分析技法は昔から研究されており、研究と実践を繰り返し生み出されています。従来の方法論や技法を振り返る事は大切です。これから、オブジェクト指向分析が誕生する前の方法論と技法を簡潔に説明します。
 分析技法が生み出される前は、ソフトウェア開発は混沌そのものでした。開発者の経験と感性に基づき、開発作業が進められました。しかし、開発規模が大きくなるに従って、開発者の経験と感性だけに頼る方法は通用しなくなりました。ソフトウェア開発における数多くの問題は、現実と情報処理機器の差異から発生します。現実世界は抽象的で、そのままでは機械が処理できません。現実の捉え方が重要になってきます。そこで、現実をモデル化する方法と物事の見方である各種方法論が考えだされました。
 最初に考えられたのは、現実世界を機能の塊として捉えるプロセス中心アプローチです。プロセス中心アプローチでは、現実世界を情報の入力・処理・出力として捉えます。この考え方は有益だったのですが、プロセスは変化しやすいものであり、変化に耐えられないという弱点がありました。そこで、データ中心アプローチが考えだされました。
 データ中心アプローチは、データの流れに注目します。プロセスは業務手順が変われば変化するが、データそのものは変化しないという考え方をします。例えば、発注手順(プロセス)は変化しますが、発注データは業務の内容が変わらない限り変化しません。この考え方により、ソフトウェア開発が行いやすくなりましたが、プロセスを無視できないという弱点がありました。
 そうした方法論は数多く考えだされましたが、それが混乱を引き起こしました。何故ならば、それらアプローチ法は、ソフトウェア開発の一部分で有効なものであり、全てのソフトウェア開発に適したものではなかったからです。そこで、具体的な技法である、構造化分析が考えだされました。続く...

テーマ : ソフトウェア開発
ジャンル : コンピュータ

アジャイル開発と業務分析7

 この記事は、アジャイル開発と業務分析6の続きです。前回は、業務分析とアジャイル開発の関係を解説しました。今回も、業務分析とアジャイルの関係について解説します。
 アジャイル開発に於いて、業務分析の効果は、エンドユーザーを知る事だけにとどまりません。開発作業の見える化も実現します。私が情報処理システムもしくは情報サービスを販売するのに当たって苦心している事は、お客様の満足度です。お客様に満足して頂くには、効果がはっきりと目に見えなくてはなりません。しかしながら、情報処理技術そのものは目に見えません。そこで、如何にして効果を目に見える形で提示するかが課題となります。如何に素晴らしい商品が出来ても、それが伝わらないと意味がありません。
 業務分析をアジャイル開発で適切に行うと、情報システムの導入効果が目に見えます。何故ならば、業務分析で既存の状態をモデル化しておく事により、システム導入後の効果が目に見えるからです。また、アジャイル開発でお客様に開発へ参加して頂く事により、苦労を共にした一体感が生まれます。人間は自分が参加したものや、効果が分かるものを好みます。
 業務分析は開発側の事情だけでするものではありません。お客様を如何に満足させるかも考えつつ、実施する必要があります。お客様を開発作業から締め出すのは簡単ですし、そうする事により監視されず気が楽になるかもしれません。しかし、我々は商売で開発を行っているのです。苦労してでも、お客様の信頼を勝ち取り、満足して頂ける商品を提供しなくてはならないのです。その点、目に見えない情報システムが不利だと言われていますが、私はそう考えておりません。開発工程に参加して頂く事により、商品がつくられる工程を体感して頂けるという大きな利点があります。お客様は分かってくれないと嘆くよりも、分かってもらえる努力をしなくてはなりません。常にお客様に見られている事の苦労はありますが、大きな達成感が得られますので、情報処理技術を習得する事の幸せを噛みしめられます。
 作業が隠蔽されているウォターフォール開発モデルよりも、アジャイル開発で業務分析を行うと効果が高いと言えます。

テーマ : ソフトウェア開発
ジャンル : コンピュータ

Win32並行処理プログラミング入門10

 この記事は、Win32並行処理プログラミング入門9の続きです。前回は、グローバル変数を使用する事による問題と、解決方法のひとつとしてInterlockedExchangeAdd関数がある事を解説しました。今回は、InterlockedExchangeAdd関数とその背景について解説します。
 前回のサンプルで示したように、並行処理プログラミングでグローバル変数を使用すると、インクリメント処理の様な単純な処理でも問題が発生します。オブジェクト指向プログラミングを実践している人は、グローバル変数を極力使用していないと思いますが、使用しても処理は出来ます。しかし、並行処理プログラミングでは、グローバル変数を使用すると必ず問題が発生します。その原因は、共有メモリに対して並行に処理をするからです。
 インクリメント処理をアセンブラで考えると、何故正常にカウントされないのかが分かります。インクリメント処理は、メモリから値を取り出してレジスタに格納してから、レジスタ上の値をインクリメントし、レジスタの値をメモリに書き込まなくてはなりません。しかし、並行処理を行うと、レジスタの値が、インクリメント処理の途中で違う変数の値に変わってしまうかもしれませんし、レジスタの値がメモリ上の値と異なってしまうかもしれません。それに加えて、アセンブラレベルの操作は、処理を最適化するために実行順序が変えられる事すらあります。
 これらの問題を解決するには、インクリメント処理をアトミックに実行しなくてはなりません。アトミックを簡潔に表現すると、一つの処理が他の処理に割り込まれずに実行される事です。先ほどの例でいうと、インクリメント処理は、読み込み・変更・書き出しの3つの処理で成り立っています。この3つの処理の間に他の処理が割り込むと、値が予想外のものとなってしまいます。ですから、この3つの処理をしている間、他の処理が割り込まないようにしなくてはなりません。それを実現するのが、InterlockedExchangeAdd関数です。
 InterlockedExchangeAdd関数の使用方法は簡単です。long型の変数のアドレスと、加算する値をパラメータとして渡して実行するだけです。減算したい場合は、マイナス値を指定するだけです。並行処理をする際は、単純な計算でも注意を払わなくてはなりません。もちろん、初めからグローバル変数を使用しない事が一番の解決法です。続く...

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

中の人の徒然草387

ピヨメリークリスマス♪昨日はクリスマスを楽しみました。


妹「ああ、今日に限って、なんで残業なんだろうッ?!!!」
私「それは運が悪いな。僕は仕事お休みにするからのんびり過ごすよ。」
妹「お兄ちゃんは、好きな時仕事が出来るからいいな~。」
私「いや、そんなことないよ。取引先から緊急連絡が入ったら対応しなくちゃいけないし・・・」
妹「もぅ、クリスマスに仕事しているなんて馬鹿々しい。ああ、馬鹿ップルを殴りたい!」
私「(笑)それにしても、なんでそんなにクリスマスに拘るんだ?うちは家族で過ごすと決まっているから、彼氏とデートも出来ないだろ?」
妹「彼氏?そんなのいないよ。クリスマスと言えば、ケーキよ!ケーキ!ケーキを食べたいの!」
父「なんだ?朝から何騒いでいるんだ?ケーキならちゃんと予約しているぞ。」
妹「聞いてよ、お父さん。うちの馬鹿上司、クリスマスに長すぎる残業を強要するんだよ!」
父「ッ!という事は・・・○○(妹の名前)と一緒にケーキを食べられないのか・・・そうか・・・」
別の家で住んでいるから会えない父は、寂しげな何とも言えない表情をした。
妹「・・・なんかごめん・・・」
自分に言い聞かせる父「仕事だから仕方がないよな。仕方がないよな。」
私「明日一緒にケーキ食べよう。」
父「2日連続楽しもうと思って思って8号を買ったんだが・・・」
私「えっと・・・それは一日で食べきれる量ではないな・・・深夜○○と一緒に食べるよお父さん。」
という事で、夕方は実家で母と父とクリスマスパーティを、深夜は妹と一緒にクリスマスパーティをしました。妹がかわいくて仕方がない父にとっては残念なクリスマスだったけど、私は2度クリスマスパーティをしたので楽しかったです。
今日も家族水入らずでクリスマスパーティをします。

テーマ : 裏事情
ジャンル :

ネタつつき89ー不思議な事をするIT業界

 私は色々な業界の人と話しをします。ですから、IT業界特有の不思議な事が目につきます。今回はそのうちの意一つをネタにします。気楽に読みつつ、日本のIT業界がこのままでいいのか少しだけ考えてみて下さい。
 人件費削減のため、実装工程を下請けに投げるという会社が沢山あります。私はこれが不思議でなりません。人件費が問題であるならば、設計しかしない、文章しか書かない、パワーポイントしか使わない・・・といった人を何故作り出すのでしょうか?彼らも入社する前は、IT業界はプログラミングが必須技術であり、設計もプログラミングも必要とされる、高度な花型職業だと考えていたはずです。今はもう、IT業界の理不尽な体質がばれて、そう考える学生も減ってしまったようです。IT業界が自身の仕事の価値を減らしてしまったので人気がないのです。花型職業であれば、人気は自然に上がる筈です。
 しかし、日本のIT業界は、35歳以下の人間しかプログラミングをさせません。役職を与えて、無理やり現場から遠ざけてしまいます。しかし、そんな事をすれば、ドックイヤーなこの業界ではよい人材だと言えなくなります。技術を知らない技術者に何の意義があるのでしょうか?
 それにも関わらず、日本のIT業界は情報処理技術(IT)を極める事を無理やり断念させます。そして、大切な実装作業を海外や国内の弱小企業に投げてしまいます。その理由が人件費の削減だと言われています。その理論は論理的整合性がありません。
 人件費を削減したいのであれば、他の会社に仕事を投げないで、自社の人間に仕事をさせればいいのです。人間は誰しも完璧ではありませんから、プログラミングが苦手な人もきっといるでしょう。しかし、開発はチームで行うものですから、プログラミングが得意な人もきっといる筈です。いなければ、それは人事の問題であり、人的資源の管理が出来ない会社である事を示しています。
 実際海外では設計も実装も出来るのが当たり前です。海外の会社に聞けばきっと、「人件費のコストを考えると設計だけしかしない人は要らない」と言うと思います。これは考えれば直ぐに分かる事ですが、両方するほうが開発に必要な人数も減り人件費は減ります。多重請負にする方が人件費が高くなります。
 この件について、とあるIT会社の社長に聞いたところ、教育にかけるお金がないとの返事が返ってきました。日本は教育と言えば、新卒を雇ってお勉強をさせると考えているようです。しかし、プロの教育とはそんなものではありません。実践で習得するものです。とはいえ、日本の学校教育は、自分で思考する力を鍛えていないという残念な結果が出ていますので、基盤が駄目だから会社側もそうせざるを得ない部分があるのかもしれません。ならば、新卒だけを雇うのを止めればいいと思うのですが、日本の制度は新卒を入社させる事が前提となっているので、経営上難しいようです。
 色々な問題が絡んでいますので解決が難しい問題です。ただ、これだけは言えます。製品の質を向上させる努力をしないIT業界はどうかしています。IT会社なのに、技術者を鍛錬させないのは明らかにおかしいです。無理やり、技術者の鍛練を妨害し、変な階級構造を作り上げ、技術者の腕をなまらせるというのは自殺行為に等しいでしょう。まともな業界になる事を祈っています。

テーマ : ソフトウェア開発
ジャンル : コンピュータ

プロフィール

インドリ

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カウンター