より深く本システムを利用するために


VIOSにおけるプログラミングは、C言語に非常に良く似たVPEーpと言う言語を使用して行います。
VPEーpはインタープリタ言語であり、必要最低限の命令しか持っていません。
しかし、ユーザが追加命令を作成するにより並列画像処理を行うことが出来るようになります。
追加命令は、VPEーpで記述します。それはVIOSにより一端C++のソースに変換、そしてコンパイル
され、VPEーpの1命令として組み込まれます。
従ってこの変換を理解することは、VIOSによるプログラムの理解につながります。
 
 


それでは各命令の変換の概要について順に説明します。なお、これはあくまでイメージであり、
実際にこのままのC++ソースに変換されるわけではありません。
 

  • parallel { }
  • for(y = □; y < ■; y++)
       for(x = ◯; x < ●; x++) { }
    sync();
      このように変換されます。□、■、◯、●にはそれぞれ実行時に各実行単位に割り振られた画像
    の各頂点の値が入れられます。つまり、実際にはip1の数に処理が分割されるのみで各p1では処理
    は逐次実行されていることになります。また、並列部の最後にはsyncにより全ip1の同期を取ります。
     
  • 逐次実行部
  •   まず、最初のsyncで全ip1の同期を取ります。そして、ある特定のip1(idが0である)の場合のみ
    逐次実行部を実行します。そして、最後にsyncで全ip1の同期を取ります。
     
  • 内部関数( width(), height(), hotx(), hoty() )
  • image_name->width
    image_name->height
    image_name->hotx
    image_name->hoty
      関数の形式をしていますが、このように指定した画像構造体のメンバ変数からの読みだしになる
    ため、別変数を設ける必要はありません
     
  • 大域変数へのアクセス(デフォルト・排他制御あり)
  •   このようにアクセスするたびに必ず一貫性処理を行います。
     
  • 大域変数へのアクセス(mutexオン・排他制御なし)
  • /* 読みだしの場合 */
    x = value;

    /* 書き出しの場合 */
    value = x;

    /* ただしparallel文の最後 */
    sync();
    join(value);
     

      処理中の一貫性処理は無くなり、各ip1ごとに独立した変数として扱われます。しかし、
    parallel文の最後において指定した結合処理に基づいて一貫性処理がなされます。
     

    次に、各命令の内部構造および、特定の場合において必要となる特殊な記述方法について説明します。
     
  • parallel文を繰り返し文により囲む場合

  •  

     

    この場合、繰り返しの変数を排他制御あり(デフォルト)にすると内部では、
     

    if(ip1_id == 0) {
        for(i = 0 && global_write(i) ; global_read(i) && i < ◯; i++ && global_write(i)) {
            signal(id, 1);
            /* このparallel文も本当は展開されてます */
         parallel {}
        }
        signal(id, 0);
    } else {
        /* このparallel文も本当は展開されてます */
        while( wait(id) > 0 ) parallel {}
    }
    と、展開されます。これでも実行されますが、繰り返しの回数が増えると排他制御の回数も増え、
    実行時間の無駄になります。
      そこで、このような場合は繰り返し変数iを排他制御なし、結合方式を最大値結合に設定します
    (#vios mutex i off max と宣言します)。
      こうすると、以下のように展開されます。iはparallel文が一回終了するごとに結合されるので、
    並列処理中で正しく使用できます。
     
    if(ip1_id == 0) {
        for(i = 0; i < ◯; i++) {
            signal(id, 1);
            /* このparallel文も本当は展開されてます */
         parallel {}
        }
        signal(id, 0);
    } else {
        /* このparallel文も本当は展開されてます */
        while( wait(id) > 0 ) parallel {}
    }
  • comm命令による通信を行う場合

  • 上記のparallel文の展開法でも分かるように、VIOSにおいて実際に並列処理されているのは
    ip1単位でのみです。また、comm命令では必要となるデータが送られてくるまでウェイトします。
    よって、parallel文が2重for文に展開された際、先に実行される座標(左上)が自ip1内で後から実行
    される座標(右下)を待つ場合、永久にウェイトし続けます

      現在の解決法としては、

  • 発生する通信が左上から右下のみになるようにプログラムを作成する。
  • 送信するparallel文と受信するparallel文を別にする。
  • 後者について。comm命令における通信バッファは1命令中は保存されるので、まず最初の
    parallel文で送信を全て行い、次のparallel文で受信を行うことによりデッドロックを回避します。
    なお、現在この問題についての解決策を考案中です。
  • フラグによりparallel文の展開方法を変更する。
  • comm命令を拡張した複数データ通信命令を実装する。
  •    この2つを次リリースにおいて実装する予定です。


    目次に戻る