月別アーカイブ: 2008年10月

Little Big Planet

ここずっと PS3 の Little Big Planet ベータやってます。はまっています。
道路標識をチェックポイント(コンティニューポイント)と見間違えたくらい。

オンラインにあがっている様々なステージをプレイするだけでも延々遊べそうなのに、
エディットが非常に楽しいです。

自由度が高く、シンプルな物理ルールで出来ているので、
工夫次第で出来そうなことがいくらでもあります。
いかにもゲームっぽいお約束な決まり事にとらわれないのがいい。

littlebigplanet

Windows Interlocked API

Windows の Interlocked 系 API は atomic な操作に使われます。
例えば InterlockedIncrement() は load と store を含みますが、その間に他の
スレッドが同じメモリを書き換えることなく処理が完了するよう調整されます。

x64 でコンパイルするとこれらの Interlocked API はインライン展開されるようです。
下記のように同機能の intrinsic 命令が用意されおり、x64 では単なる別名として
定義されていました。

InterlockedCompareExchange Function
_InterlockedCompareExchange Intrinsic Functions

x86 でも直接 _InterlockedCompareExchange() を使えば組み込み命令として機能します。
実際のコードは下記の通り。

x64:
 lock cmpxchg dword ptr [mem32],edx  // InterlockedCompareExchange
 lock cmpxchg qword ptr [mem64],rdx  // InterlockedCompareExchange64

x86:
 lock cmpxchg dword ptr [mem32],edx   // InterlockedCompareExchange
 lock cmpxchg8b qword ptr [mem64]     // InterlockedCompareExchange64

InterlockedIncrement() + x64 の場合

// 返値参照あり
mov ecx,1
lock xadd    dword ptr [mem],ecx
inc ecx

// 返値参照無し
lock add     dword ptr [mem],1

返値を参照するかどうかによって、命令そのものも置き換わっています。
単なる関数や asm 文の inline ではなく、組み込み命令であることがよくわかります。

以前紹介した Gamefest2008 のスライドによると DirectX11 の Compute Shader
には下記の命令が追加されるようです。

 InterlockedAdd()
 InterlockedMin()
 InterlockedMax()
 InterlockedOr()
 InterlockedXor()
 InterlockedCompareWrite()
 InterlockedCompareExchange()

Gamefest 2008 Presentations
「Direct3D 11 Computer Shader More Generality for Advanced Techniques」

InterlockedMin()/InterlockedMax() は Win32 API に無い命令です。
書いてみるとこんな感じでしょうか。(厳密な動作は未検証)

template
void InterlockedMin( T volatile* mem, T val )
{
    union {
        T      fval;
        long   ival;
    }	cur;
    do{
        cur.fval= *mem;
        if( cur.fval <= val ){
            break;
        }
    }while( _InterlockedCompareExchange(
                reinterpret_cast( mem ),
                *reinterpret_cast( &val ),
                cur.ival ) != cur.ival );
}

関連エントリ
Direct3D11 Compute Shader など
SSE3 の monitor mwait 命令

SSE3 の monitor mwait 命令

SSE3 で monitor / mwait 命令が追加されています。
HT やマルチコアなど、ハードウエアスレッドの同期効率を上げるために有効
らしいですが、使ったことがないので調べてみました。

monitor で監視アドレスを与えた後、mwait 命令は監視アドレスに何らかの
書き込みがあるまで待機します。
メモリの更新をハード的に検出する動作は RISC 系の atomic 命令 ll/sc に
似ています。

イベント待ちのような動作なので様々な通知に使えそうです。ただこれが OS では
なく CPU そのものの命令で実行されるため、いくつかの疑問も生じます。
CPU レベルの命令でアプリケーションがこのような動作を行って問題無いのか、
割り込みやコンテキストスイッチ等でどのように振る舞うのか、
mwait に復帰できるのか、monitor の状態がリストアされるのか、など。

intrin.h を include するだけで、_mm_monitor() / _mm_mwait() の
intrinsic 命令が使えます。
実際に x86 でも x64 でもコンパイルは可能ですが、無効な命令となり実行は
出来ませんでした。
CPUID を調べると、MONITOR/MWAIT に対応していることは確認できます。

Intel 64 and IA-32 Architectures Software Developer’s Manuals
日本語技術資料のダウンロード

マニュアルによるとどうやら特権命令らしく、無条件で使えるのはレベル 0
の場合のみ、特権レベル 1~3 での動作も可能だけど、そのためには何らかの
条件がいるそうです。
また MONITOR/WAIT が使えるかどうかは MSR IA32_MISC_ENABLES (1a0) の
bit18 の設定にも依存し、この値が 0 だと CPUID のフラグも落ちるとのこと。
この値も設定されており問題はなさそうです。

Manual の Volume 3A 7.11.3 で、特権レベル 1 以上の場合でこれらの命令が
使えるかどうか判定する方法が載っています。intrinsic で書くと次の通り。

__try{
    _mm_monitor( memory, 0, 0 );
}
__except( 1 ){
   // 使用できない
}

つまり Illegal Instruction が発生するのは特権レベル 0 以外は使えないことを
意味しているようです。何らかの設定で無効にされているのか、それとも
もともと使えないものなのか、その条件はわかりませんでした。

マニュアルを見ると mwait の動作は、割り込み等によって頻繁に解除される
ようです。mwait に復帰することはなく、監視したメモリの値を調べて解除原因を
判断する必要があるようです。

また監視メモリの領域は CPU 依存で、CPUID の 0x05 で調べることが出来ます。
手持ちの CPU では下記の通り。最小も最大も 0x40 == 64 でした。

CPUID (CPU-Z によるレジスタダンプ)
・Atom N270
 0x00000005 0x00000040 0x00000040 0x00000003 0x00020220
・Core2 Duo E6600
 0x00000005 0x00000040 0x00000040 0x00000003 0x00000020

よって何らかの変数を監視するよう割り当てても、同じ 64byte 以内に
割り当てられた他の変数へアクセスによって解除される可能性もあります。

(1) 判定用メモリ領域 64byte (CPUIDで判定) を用意して初期値を入れる
(2) monitor 実行
(3) monitor 命令実行中に書き換えられている可能性があるので判定する。
  書き換わっていたら値によって適切な分岐。
(4) 書き換わっていなければ mwait
(5) 解除されたらその要因を調べる。
  値が書き換わっていたら値によって分岐。
  書き換わっていなければ (2) へ戻る。

もし使うならこのような手順になるようです。
つまりスピンロック時に監視アドレスを与えて停止させられるため、
ループ中に導入することでバスアクセスを減らし、効率を上げることが出来ます。
でも使えませんでした。

EMONSTER lite S12HT と ATOK for WindowsMobile

以前こちら で触れたように 対応機種一覧 で非対応と書いてありますが 購入してみました。

ATOK for WindowsMobile

EMONSTER lite S12HT へもインストールは可能で、一応 ctrlswapmini lite を
使って、2タッチ/ポケベル入力を行うことが出来ました。トグル入力も可能ですが
キーだけで文字種切り替えが出来ないので難があります。

「非対応」と書かれている理由は、やはり ATOK だけではテンキーによる文字入力が
出来ないためでしょう。
外部でトグル入力やポケベル入力出来るソフトなどを組み込めば、テンキーでも
それなりに使用できるものになると思われます。

また今まで他の機種に内蔵されていた ATOK とほぼ同じで、キーコマンドへの対応
状況や反応も同じ。ソフトからの制御も同じように出来そうです。

例えば Wnn や FSKAREN ではできなかった、確定のみで改行しないキーコードが
使えるため ctrlswapmini との相性も良いです。
ただし ctrlswapmini lite 1.02 は、Wnn 対応のためにこの動作を省いているので
今のところ恩恵がありません。

ATOK 設定の「バージョン番号」のタブにも、特にバージョン番号らしきものが
無いので、手持ちの EM・ONE 内蔵のものと完全に同じかどうかはわかりません。

現在 EMONSTER lite S12HT には、これで 4つの IME が同居しています。
同時に使えるのは一つだけで切り替えは再起動を伴うため、メモリ的にも特に
問題はなさそうです。

使用できる IME のまとめ

    確定のみ テンキー文字入力 外付けキーボード
MS-IME   ○      ×        ○
内蔵Wnn   ×      ○        △(スライドで切換え)
FSKAREN   ×      ○        ×
ATOK    ○      ×        ○

テンキーによるトグル入力処理は、サポートソフトを何も入れない単体の状態だと
Wnn と FSKAREN のみ可能です。
ただし IME 自体が自前でテンキーのトグル処理を行っているので、それぞれ
持っている機能や細かい操作性が異なります。このあたりは好みの問題も出てくる
でしょう。2タッチ/ポケベル入力はそのままでは出来ません。

テンキーの文字入力処理に対応すると数字キーを乗っ取ってしまうために QWERTY
キーボードとの同居が出来なくなります。外付けキーボードを使った場合などに
問題が生じます。
上の表でも、テンキー入力と外付けキーボード対応はほぼ排他です。

唯一 FSKAREN のみ、テンキーのスライドに応じてモードを切換えてくれるので、
一応両方使うことが出来ます。
テンキー専用機種とそうでない機種との違いは、FSKAREN 自体のバイナリを
個別に分けることで対応しているようです。

●外付けキーボードとの相性で問題が生じる原因

・テンキーによる文字入力に対応していると、数字キーが乗っ取られてしまう
  IME 側でテンキー入力処理を一時的に解除する機能が必要

・変換操作がスペースや変換キーでできない(カーソルキーのみなど)
  操作キーをカスタマイズできる機能が必要
  または外付けキーボードを考慮したキーバインドをあらかじめ行っておく

・変換や文字入力モードを切り替えできない
  テンキーに特化した IME だと、漢字、全/半、ひらカタキーなどで文字種を
  切換えられないものがある。

●ctrlswapmini との相性で問題が生じる原因

・キーストロークだけで文字種を変更できないものがある
   そのため IME 制御を行って、IME の on/off だけで英数とかな入力を
   切換えなければならない。

・変換バッファの確定だけ行って改行しないキー操作が必要
   IME 制御を行う場合、未確定バッファを捨てないで済むために必要。
   IME 制御をしなくても良いなら無くても何とかなる。

・一時かなモードの使用
   ローマ字入力モードでありながら、かな入力のシミュレートが出来る
   特殊なキーシーケンス。英語キーボードと見なす端末だとそもそも
   かな入力自体ができないようです。

プログラム側から見ると、MS-IME + 日本語キーボードとみなす場合が一番問題が
少ないです。次はおそらく ATOK だと思いますが、単独でテンキー入力出来ないし
まだほとんど調べていないため、まだ何ともいえません。

関連エントリ
WindowsMobile IME FSKAREN / ATOK
EMONSTER lite S12HT IME FSKAREN