なが月・24日目

24日目

午前

今日はまず先週できなかった並列プログラミングに再挑戦した。最も初歩的なコードとして

//出典: http://onoono-life.blogspot.com/2014/04/ccopenmp.html
#include <stdio.h>

int main() {
#pragma omp parallel
    {
        printf("parallel\n");
    }
    return 0;
}

をCLion上で書き、WSL上のUbuntu(gcc/g++5.4.0)で

gcc/g++ -Ofast -fopenmp /mnt/<Windowsディレクトリ上にあるmain.cへのフルパス>

とすることでUbuntuのカレントディレクトリにa.outが出た。

export OMP_NUM_THREADS="4"

環境変数を設定したうえで./a.outとすると、無事にWSL上で4行parallelと表示された。これで一安心である。19日目の記事でWSLでもダメだったというのは何だったのか分からない。

脱線するがC++AtCoderの問題を解いてGitHubに上げる時、main.cppをコミットすると上書きされてしまうので、解答中はmain.cppに各問題の答案を書いては消し、その日の取り組みが終わったときに自分の提出コードをコピーしてabc1xx_x.cppに貼り付ける作業をしている。これをどうにかできないかと調べていた時にstd::vectorでも.atではなく[]で要素にアクセスできることを知った(Out of Range例外は出なくなる)。.atは見づらかったので今後の答案には[]を使う。

さてC++でもOpenMPを試す。C++特有のデータ構造でもOpenMPが動くか確かめるため、以下のコードを書いてコンパイルし実行した。

#include <bits/stdc++.h>
#include <omp.h>

int main() {
    std::vector<char> alphabets(26);
    char c = 'A';
    for (int i = 0; i < 26; ++i) {
        alphabets[i] = c;
        ++c;
    }
#pragma omp parallel for
    for (int i = 0; i < 20; ++i) {
        printf("%c %d / %d\n", alphabets[i], omp_get_thread_num(), omp_get_max_threads());
    }

    return 0;
}

行頭にはAからTまでが各スレッドの担当範囲では順番に、しかし全体としてはバラバラに出力されるはずである。

i7-6700(4C8T)で、環境変数OMP_NUM_THREADSがないときの実行結果は

M 4 / 8
N 4 / 8
S 7 / 8
T 7 / 8
A 0 / 8
B 0 / 8
C 0 / 8
G 2 / 8
...

となり、omp_get_thread_num()が0-based indexであり、また全スレッドを利用して並列出力を行っていることが確認できた。

午後

VR制作では、まずStandard AssetのCarに付属するライトとエンジン音の調査の続きを行った。ヘッドライトはパーティクル用の加算シェーダを使って周囲を光らせ、スポットライトで地面を照らしている。テクスチャはPhotoshopを使えばぼんやりと光る感じのものが作れそうだ。スポットライトはそのまま使えばよいだろう。

エンジン音は速度とギアに応じてピッチを変えているようだが、レースゲームではないので速度だけを参照するようにして、あとはピッチを各車両に合わせて調整する予定。むしろ交差点のような低速交通の場合は横を通る時の道路音のほうが重要だと思うので、それを録音して使っておきたい。

列挙型と剰余を用いて、東西南北いずれから出現した時にも場合分けをすることなく一律の処理を行って目的地を設定することができ、方角ごとに異なるスクリプトをアタッチし別のPrefabを作っていた悪夢のようなワークフローから脱却できた。

明日は信号の影響範囲を今回のマップに合わせて調整し、車線変更、段階的目標システムの実装まで行いたい。