IEEE Haptics Symposium 2018に行ってきた

趣味でやっている研究活動の一環で
触覚に関する国際会議の1つの IEEE Haptics Symposium 2018 に行ってきた.
会社でまるまる有給をとり,共著の方の援助を受けサンフランシスコへ.

f:id:yusuke_ujitoko:20180405210024j:plain

普段は深層学習まわりしか記事にしてきていなかったが、
今回は触覚にまつわる研究について少しだけ紹介。

形状ディスプレイ

ピンアレイ型形状ディスプレイのデモ。

バーチャル空間の物体に触ったときの物体形状をピンを制御して提示する。
実際触ったのは初めてだったので感激した。

錯覚を使ったテクスチャ提示法

Anatole Lécuyerのところの錯覚を使った触覚提示も興味深かった.
視覚によって触覚が引っ張られることを利用したpseudo-hapticsの一種の展示.

タッチスクリーンでは,指と視覚提示部が同時に視認できてしまうので,
この種の錯覚は提示するのが難しいと言われていたが, それにチャレンジしようという研究.

ちなみに我々の研究グループが発表したのもタッチスクリーンでのpseudo-hapticsについてで、 重さや抵抗感の提示を試みる新たなアプローチに関するものだった。

その他

篠田研のテニス鑑賞映像への振動付与システムの完成度がとても高く,
梶本研の指先への触覚を手首に提示するシステムも、
奇抜な見た目にも関わらず直感的でよかった.

終わりに

これまでまともな触覚系学会には行ったことなかったが、
今回機会を頂けて行くことができてよかった。

「会社休んで趣味で来てます」 というと結構驚かれてインパクトがあるようなので、
今後もこの方針で活動を続けて、キャラを育てていきたい。 f:id:yusuke_ujitoko:20180404215339p:plain

6月のEuroHapticsでも別のテーマで発表します。
コンテンツに応じた触振動刺激の自動生成をGANを使って行う研究です。
立て続けに会社を休むわけにもいかないので、こちらは共著者の方に発表はお任せしますが..。

スレッドの管理

Linuxとpthreadsによるマルチスレッドプログラミング入門を読んでいる。
この記事は第二章のメモ。

スレッドを作る

本に書いてあったことはだいたい知ってたので、man pthread_createしたときのメモを載せてみる。

  • threadは以下のいずれかの終わり方をする
    • スレッド内でpthread_exit()を呼ぶ。このときexit statusを指定できる。
    • pthread_create したときの指定関数の返り値で終わる。これはpthread_exitと同じ。
    • pthread_cancelされる
    • どれからのスレッドでexitが呼ばれる

  • デフォルトのスタックサイズは2MB

  • Linux 2.4からはgetpidするとTGID(thread group identifier)が取得できる。同じプロセス内でスレッドを立ち上げた場合にはTGIDは同じ値なため、同じものが得られる。
    • 実際確かめてみたら同じになった。
スレッドの終了
  • pthreadではスレッド間に優劣や親子関係があるのではなく、プロセス内のすべてのスレッドが原則として対等である
スレッドIDとスレッド終了待ち

man pthread_joinを読む。

  • int pthread_join(pthread_t thread, void **retval);はthreadで指定されたスレッドの終了を待つ。もし既に終わっていたら、すぐpthread_join()は帰ってくる。
  • retvalがNULLでない場合、pthread_join()はスレッドのexit statusをコピーして、*retval で指定される場所に格納する。
  • 複数スレッドが同時にjoinしようとしたときの挙動は不定
  • 一回joinしたあともう一度joinするときの挙動も不定
    • なのでjoinしたらthreadにNULLを入れておき、joinの事前にチェックしておくなど対策要。
  • joinableなスレッドをjoin失敗した時はゾンビスレッドが生まれてしまう。
スレッドの同定
  • pthreadではpthread_self()を使ってスレッドIDを取得できる。
    • LinuxではスレッドIDは単純な数値になっている。しかし、OSやCPUの都合によりpthread_t型は単純な数値型にならないことがありえる。pthread_t型の比較にはpthread_equalを使うことを推奨。

      POSIX.1 allows an implementation wide freedom in choosing the type used to represent a thread ID; for example, representation using either an arithmetic type or a structure is permitted. Therefore, variables of type pthread_t can't portably be compared using the C equality operator (==); use pthread_equal(3) instead.

    • スレッドIDはプロセス内でユニークである。でもスレッド終了後には再利用される可能性がある。
スレッドの属性
  • スレッドの属性については、OSやライブラリのバージョンの違いによって正しく機能しないことがある。デフォルトの属性(NULL)推奨。
他のスレッドの強制停止
  • pthread_cancelをすると他のスレッドを停止できる
    • でもリソースの解放はされない。メモリリークの温床になる。できるだけ使わない。

マルチスレッドプログラミングとは

Linuxとpthreadsによるマルチスレッドプログラミング入門を読んでいる。
この記事は第一章のメモ。

pthreadに関する基本的な知識はあるので序盤はあんまりメモしなくて良いかなという感じで読み始めた。

マルチプロセスとマルチスレッドの違い
  • コンテキストスイッチの重さ
    • マルチプロセスの場合、コンテキストスイッチする前にその実行環境(メモリ内容などのリソース状態)を保全して、後で戻ってきた時のメモリ内容などを戻さないといけないため、比較的重たい。
    • マルチスレッドの場合、コンテキストスイッチする際に保全しないといけない情報はプログラムカウンタやスタックポインタなどの極小数の情報だけで済む。高速。
マルチスレッドプログラミングの基本要素
  • pthreadで重要なのは高々15種類
    • その他はOSやライブラリのバージョンによって挙動が違ったり、利用に特別な注意が必要。

  • pthreadには動作を一時停止する関数はない。スレッドでの動作を一定時間停止するには標準ライブラリ内のsleep関数やnanosleep関数を用いる。
  • 他のマルチスレッドシステムでは、他のスレッドの処理の割り込みを許す、という動作を指示する関数が用意されている(yield)。しかしpthreadは原則として「常に他のスレッドの割り込みは許されている」というポリシーで作られているため、yieldに相当する関数は存在しない。

Linuxでスレッドの動作コアを確認する

マルチスレッドプログラミングではテスト時にスレッドの動作コアを確認したい。 その方法をメモ。

システムモニタを使う

sudo apt install indicator-multiload //インストール
indicator-multiload //実行

タスクバーに出てくるシステムモニタをクリックすると、 コアごとの使用率がリアルタイムに見られる。 f:id:yusuke_ujitoko:20190110091259p:plain

https://www.eidos.ic.i.u-tokyo.ac.jp/~tau/lecture/operating_systems/gen/ex/threads_processes/

コマンドライン

psを使う
ps -aF //実行

とすると、

UID        PID  PPID  C    SZ   RSS PSR STIME TTY          TIME CMD
ujitoko   7751  7740  0  5462  2988   6 20:58 pts/2    00:00:00 tmux
ujitoko  17448  9599  5 415600 116896 2 21:30 pts/20   00:00:08 /usr/bin/mono /usr/lib/pinta/Pinta.ex
ujitoko  18018  7754  0  9594  3276   2 21:33 pts/19   00:00:00 ps -aF

プロセスごとの動作しているコアがPSR列に表示される。

htopを使う
sudo apt install htop //インストール
htop //実行

htopを使うとグラフィカルにコア動作状況がわかる。

f:id:yusuke_ujitoko:20190110213215j:plain

シグナルハンドラを書く最小サンプル

#include <signal.h>
#include <stdio.h>
#include <unistd.h>

void sigcatch(int);

int main() {
    pid_t pid = getpid();
    printf("PID:%d\n", pid);

    if (SIG_ERR == signal(SIGHUP, sigcatch)) {
        printf("failed to set signal handler.n");
        exit(1);
    }

    if (SIG_ERR == signal(SIGINT, sigcatch)) {
        printf("failed to set signal handler.n");
        exit(1);
    }

    while (1) {
        sleep(1);
    }

    return 0;
}

void sigcatch(int sig) {
    printf("catch signal %d\n", sig);
    exit(1);
}

実行時に表示されるプロセスIDに対して,kill -INT XXXXXkill -HUP XXXXXをするとシグナルハンドラが実行される.
プロセスIDを調べるときは上記サンプルのように,プロセスIDを標準出力してもよいし, ps u | grep a.outという感じでコマンドを打って確認してもよい.