Ubuntu9.10, nVidiaなカード:症状別xorg.confの直し方

apt-get remove python したらいろんなものが消えてしまって大変なことになったのでOSを再インストール。そしたらまた画面設定でハマったのでメモ・・・。基本的にはこの間のエントリの加筆。

今回は参考文献なしなので間違ってるかもしれない。注意。ちなみに Separete X screen + Xinerama に設定しようと頑張った形跡です。

python消しちゃダメだよ!危険!

nvidia-settingsの画面の位置設定で、画面をマウスカーソルでグリグリ動かせないんだけど!

両方のモニタの位置を Absolute にしないとダメ。 Left of とか Right of にしておくとマウスで動かせない。

縦置きした画面が1080x1920じゃなくて1920x1920になっちゃうよ!(画面端までマウスカーソルを持っていくとスクロールしちゃうよ!)

縦置きしたモニタの Section "Screen" を見よう。

Section "Screen"
    Identifier     "Screen1"
    Device         "Device1"
    Monitor        "Monitor1"
    DefaultDepth    24
    Option         "TwinView" "0"
    Option         "metamodes" "DFP-1: nvidia-auto-select @1920x1920 +0+0"
    SubSection     "Display"
        Depth       24
    EndSubSection
EndSection

こんな感じになってると思う。

この SubSection "Display" に

        Virtual 1920 1080

これを加えよう。 "Virtual 幅 高さ" という感じ。ただし幅と高さは回転前のものを入れること。数値は環境に合わせて適当に変えてね。 nvidia-auto-select なんちゃらのところに書いてある1920x1920は変えなくて大丈夫。

アプリケーションが画面をまたいで移動しないよ!

Section "ServerFlags"
    Option         "Xinerama" "0"
EndSection

こうなってるか、もしくはこのセクション自体がないかも? "0" を "1" に変えると解決。

マウスが画面をまたいで移動しないよ!

(縦置きした画面(Screen 1) が左側にあります)

Section "ServerLayout"
    Identifier     "Default Layout"
    Screen      0  "Screen0" 1920 840
    Screen      1  "Screen1" 0 0
    InputDevice    "Keyboard0" "CoreKeyboard"
    InputDevice    "Mouse0" "CorePointer"
EndSection

Screen 0のx座標が間違ってる!縦置きしてあるので1080から始まるよ。

設定変更が反映されないよ!

sudo cp xorg.conf /etc/X11/xorg.conf

X再起動前にコピーを忘れずに!xorg.confのバックアップも忘れずに!

Ubuntu 9.04 で縦置き+横置きのデュアルディスプレイ環境を構築 with nVidiaなカード

相当はまったのでメモ。

手順

  1. 念のため xorg.conf をバックアップ
  2. nvidia-settings で雛形となる xorg.conf を生成
  3. 生成された xorg.conf をちょこっと書き替えて完成

xorg.conf をバックアップ

/etc/X11/xorg.confをどこか適当なところにバックアップする。

nvidia-settings

X Server Display Configurationを選択。Configuration(Configure...をクリック)で Separete X screen を選択する。Resolutionとかはautoで十分だった。配置とかもこの段階で適当に決めておくと楽。

位置などの調整が終わったらApplyをして、 Save to X Configuration File をクリック。そして、どこか適当な場所に xorg.conf を生成して貰う。

生成された xorg.conf を書き替え

出力された xorg.conf の中身を見て、

Section "Device"
    Identifier "Device0"
    ... 以下省略...

的なものが書かれている場所を探す。たぶんデュアルディスプレイなら2個書かれているので、縦置きしているのがどちらのデバイスか(縦置き表示したいScreenに対応したデバイスはどちらか)を判断する。どちらが目的のものか分かったら、Section "Device"のところに

    Option "Rotate" "CCW"

と書く。CCWは反時計回りという意味。CCWで逆回転してしまったらCWと書けば良いのかな?

後は今修正した xorg.conf を /etc/X11/xorg.conf に上書きしてXを再起動。

横置きの方が回転してしまったらもう片方のDeviceを回転させてみると良いよ。

Waseda.Lに参加してきました(本番)

疲れて全然日記を書く気力が起こらない。そんな自分を癒してくれるTwitterのせいで更に日記を書く気力が減ったり。しかし久々に何もすることがなくぼーっとしている日が出来たので、休みがてらWaseda.L参加報告でも書こうかと思います。

発表内容

研究用途の検索エンジンがあると良いなーという、実りのない話をしました。非常に話が発散して、分かりづらくなってしまったんですが、要約すると、

  1. 色んなところをもの凄く細かくカスタマイズ出来て
  2. 勝手に分散もしてくれて
  3. 実用的な速度で動いて
  4. 百億単位の文書の検索に対応してくれて
  5. 自分で(or他人が)作った評価対象のプログラムが使い回せて
  6. 気軽に(2,3時間程度で)機能追加ができる

研究者向けの検索エンジンを作りたいなーという話でした。作りたいなーというのがポイントで、まだ全然着手してません。しょぼくてすいません。

今僕は実用的で汎用的な検索エンジンを作っているのですが、それはまた研究用とはちょっと違うなーと思っています。Solrもかなり実用向けで優れた検索エンジンなのですが、それをそのまま研究用に使うのはちょっと微妙だと思います。逆に、研究用の検索エンジンは、実用的にはならないと思っています。そう言われると研究用の検索エンジンは無駄じゃないかと思われるかも知れませんが、研究用の検索エンジンで得られた成果を実用的な検索エンジンに反映する、というのが想定している研究用検索エンジンの使われ方です。

研究用途で使われるべき検索エンジンは実用的な検索エンジンと何が違うというのは、まだはっきり言えません。ただ、実用的な検索エンジンだと実装を固定出来る(カスタマイズ出来るようにする必要がない)機能が多いのですが、研究用だとその辺も抽象化しておく必要がありそうだということが、大きな違いではないかなと思っています。

とは言え、正直どの程度まで抽象化すべきか、というのもまだ良く分かってません。抽象化しすぎると理解不能なカオスコードが出来上がりますし、抽象化が足りないと研究によってはもの凄く大きな変更を加える必要が出てきてしまいます。本来なら相当特殊なケースには対応すべきではないのですが、研究というのは新しいものを生み出すことだと思っているので、そういう相当特殊なケースが頻繁に出てくるんじゃないかと思っています。そんな研究者が必死に考え出した新しいアイディアを素直に実装できないような検索エンジンは、研究用途の検索エンジンとしては失格だと思います。精々お勉強用の検索エンジン止まりです。ただ、それはあくまで理想であり、何かしらの妥協点は必要だと思うので、そこを見極めるのが現在の課題です・・・。

実現までには数年かかりそうな予感・・・。まだまだ知識が足りません。少なくともSIGIRの論文が問題なく読めるようになってから実装しようかなと思ってます。似たようなことを考えている人は沢山いると思うので、そう言う人達と協力して何かを作れたら楽しそうです。とりあえず最終的にはサクサク研究が進むようになるような検索エンジンが作れると嬉しいです。

Waseda.Lでは自分のモヤモヤを解消するために無理矢理発表してみたんですが、発表する前よりは頭の中で整理できたので良かったです。事情を何も知らない人に向かって話すというのは、かなり自分にとっても良いことだと思えました。現場のノリを激しく読み間違えてしまったせいで、スライドはちょっと公的な場に恒久的に晒すにはいささか問題がありすぎるので公開しませんサーセンwww

全体的に

色んな分野の人の話を聞けて良かったなーと思いました。ただ、たぶん約1名を除く全員(自分含む)が、発表対象は理系という仮定をしていたんじゃないかなとw 正直、他分野の人に伝わっているかどうかと言われれば、伝わってなかったと思います。俺も数学物理全然分からんしね。かといって、浅すぎると分かりやすいけど面白くないので、その辺の調整が難しいですよね。

疲れてて結構しんどかったんですが、Waseda.Lに参加して得たものは色々ありました。首謀者の方々本当にありがとうございました。また次回も何か話せたら良いなー。今度はノリをもう少しCS的じゃなくして行こうと思います。あと某研究室の誰かを釣って連れて行きます。

おまけ

  • tkfとsalamannはあっぷる
  • 情報系は理工の底辺
  • iPhoneを持っていない奴は情弱

Waseda.Lに参加してきました

                            Waseda.Lに参加する前に言っておくッ!
                    おれは今Waseda.Lをほんのちょっぴりだが体験した
                  い…いや…体験したというよりはまったく理解を超えていたのだが……
         ,. -‐'''''""¨¨¨ヽ
         (.___,,,... -ァァフ|          あ…ありのまま 今 起こった事を話すぜ!
          |i i|    }! }} //|
         |l、{   j} /,,ィ//|       『おれはWaseda.Lで発表していたと
        i|:!ヾ、_ノ/ u {:}//ヘ        思ったらいつのまにかiPhoneを買っていた』
        |リ u' }  ,ノ _,!V,ハ |
       /´fト、_{ル{,ィ'eラ , タ人        な… 何を言ってるのか わからねーと思うが
     /'   ヾ|宀| {´,)⌒`/ |<ヽトiゝ        おれも何をされたのかわからなかった…
    ,゙  / )ヽ iLレ  u' | | ヾlトハ〉
     |/_/  ハ !ニ⊇ '/:}  V:::::ヽ        頭がどうにかなりそうだった…
    // 二二二7'T'' /u' __ /:::::::/`ヽ
   /'´r -―一ァ‐゙T´ '"´ /::::/-‐  \    信者だとかエバンジェリストだとか
   / //   广¨´  /'   /:::::/´ ̄`ヽ ⌒ヽ    そんなチャチなもんじゃあ 断じてねえ
  ノ ' /  ノ:::::`ー-、___/::::://       ヽ  }
_/`丶 /:::::::::::::::::::::::::: ̄`ー-{:::...       イ  もっと恐ろしいものの片鱗を味わったぜ…

libhdfs: 使用上の注意

hdfsOpenはディレクトリも書き込みモードで開けます。というか、ファイルを消して、そこに新たにファイルを作ります。なのでcp的なものを作ろうとして、誤ってディレクトリに対してhdfsWriteしてしまうと…/(^o^)\

追記

他の関数も調べてみました。

  • hdfsCopy(file, dir) ---> dir/fileができた
  • hdfsRename(file, dir) ---> 失敗
  • hdfsCreateDirectory(path_to_dir) ---> 成功(ディレクトリの中身はそのまま)
  • hdfsCreateDirectory(path_to_file) ---> 失敗

うーん。インターフェイスはしっかりしているのに、内部の挙動に統一感がないな…。怖いので、念のため自前でディレクトリかどうかチェックして、処理を分岐させた方が良いかもしれませんね。

libhdfsを使う

libhdfsのAPIは$(HADOOP_HOME)/libhdfs/docs/apiに詳しいドキュメントがあるので、そこを見ながらやると簡単です。サンプルが必要ないくらいに色々書いてあります。ただちょっと良く分からなかった点があったので、いくつかメモを残しておきます。

Connect, Disconnect

HDFSへはhdfsConnectを使って接続します。この関数にはhost,portを与えます。サンプルプログラムでは"default",0を指定していますが、このように指定するとローカルファイルシステムが使用されました。HDFSのhost,portを指定したらちゃんとHDFSが使用されました。

hdfsConnectで作成したhdfsFSはhdfsDisconnectで解放します。

相対パスの扱われ方

libhdfsで関数に相対パスを与えると、デフォルトでは/user/ユーザー名/からの相対パスとして解釈されるようです。この挙動はhdfsSetWorkingDirectoryという関数で変更可能です。現在のWorkingDirectoryはhdfsGetWorkingDirectoryで取得可能です。

hdfsSetWorkingDirectory(fs, "");

のように空のものを指定すると次のようなエラーメッセージをstderrに吐きました。

Exception in thread "main" java.lang.IllegalArgumentException: Can not create a Path from an empty string
        at org.apache.hadoop.fs.Path.checkPathArg(Path.java:82)
        at org.apache.hadoop.fs.Path.<init>(Path.java:90)
Can't construct instance of class org.apache.hadoop.fs.Path for

エラーメッセージは出力されましたが、hdfsSetWorkingDirectoryは普通に-1を返すだけでプログラムは終了しませんでした。その後fsを使いまわしても特になんの問題もありませんでした。

hdfsFileInfo

hdfsGetPathInfoやhdfsListDirectoryが返すhdfsFileInfoの中身が謎だったので調査してみました。mKind以外は名前通りなので省略。

mKindは良く分かりませんが、ファイルだと70、ディレクトリだと68でした。二進法に直すとそれぞれ1000110と1000100です。謎。ドキュメントにはhdfsFileInfoについて詳しくかかれていません。mKindはtObjectKind型(enum)らしいです。tObjectKindについてドキュメントには

typedef enum tObjectKind tObjectKind

port

ソースを読めという暗黙的ですが親切なメッセージが書いてあります。見てみました。

    typedef enum tObjectKind {
        kObjectKindFile = 'F',
        kObjectKindDirectory = 'D',
    } tObjectKind;

/(^o^)\

さっきのportという謎のメッセージは、下のように書いたせいで出力されていたようです。

    typedef int32_t   tSize; /// size of data for read/write io ops             
    typedef time_t    tTime; /// time type                                      
    typedef int64_t   tOffset;/// offset within the file                        
    typedef uint16_t  tPort; /// port                                           
    typedef enum tObjectKind {
        kObjectKindFile = 'F',
        kObjectKindDirectory = 'D',
    } tObjectKind;

doxygenコメントって、"//!<"こう書かないと次の行に対するコメントになってしまうのでは。

ちなみに、mNameは次のようなhdfs://から始まる絶対パスでした。

hdfs://localhost:50000/user/nobu/test/test.txt

ファイルへの書き込み

hdfsOpenFileでファイルを開いてそれに書き込む形になります。

hdfsFile hdfsOpenFile(hdfsFS fs,
                      const char* path,
                      int flags,
                      int bufferSize,
                      short replication,
                      tSize blocksize
                      )  	

これは通常のファイル関係のAPIと同じで、ファイル名や読み書きフラグなどを引数に与えます。それに加えてHDFS上でのブロックサイズやレプリケーション数なども与えることができるようです。この辺は0を指定するとデフォルトの値が使用されます。

そんで読み書きフラグがちょっと気になったのでhdfs.hを見てみたのですが、

#ifndef O_RDONLY
#define O_RDONLY 1
#endif

#ifndef O_WRONLY
#define O_WRONLY 2
#endif

となっていました。fcntl.hでは

#define O_RDONLY             00
#define O_WRONLY             01

こうなってます。これはさすがにヤバいですね…。既に問題になっていたようです。でも、hdfs.hではfcntl.hを先にincludeしているので、LinuxではO_RDONLYは0, O_WRONLYは1になるそうです。それもそれでヤバいのではw まあLinuxだけで使っている分には大丈夫そうですね。とりあえず下手に自分でaliasなどを作らない方が良さそうです。

それでは本題のファイル書き込み。hdfsWriteを使って書き込みます。書き込んだ結果はhdfsFlushかhdfsCloseを呼び出すと反映されます。既存のファイルを書き込みモードで開くとO_TRUNC的な挙動をします。追記はできません。追記はできませんが、hdfsWriteの呼び出しは何度かに分けて行うことができます。

hdfsWrite(fs, file, "test\n", 5);
hdfsWrite(fs, file, "test2\n", 6);
hdfsCloseFile(fs, file);

次のように、hdfsFlushを複数回呼んでも大丈夫でした。

hdfsWrite(fs, file, "test\n", 5);
hdfsFlush(fs, file);
hdfsWrite(fs, file, "test2\n", 6);
hdfsFlush(fs, file);
hdfsCloseFile(fs, file);

さらに、hdfsCloseFileを呼び出さずにプログラムを終了しても大丈夫でした(絶対やらないけど)。さすが。追記ができないのであまり嬉しくはないですが、書き込み途中に不慮の事故などでプログラムが落ちてしまっても大丈夫そうです。

追記

正確には、HDFS上へ変更が反映されるのはhdfsCloseFileを呼び出したときだけかもしれないです。詳しくは分からず。サーセン。とりあえず書き込み中に情報を取得したりすることはあまりないと思うので大丈夫かな。