ラベル note の投稿を表示しています。 すべての投稿を表示
ラベル note の投稿を表示しています。 すべての投稿を表示

2021年7月20日火曜日

Unreal Engine 4 Editorの耳障りな音を変更する

変更

次のSEを置き換えればよい.
Engine/Content/EditorSounds/Notifications

この調子だとほとんどのエディタリソースを置き換える必要がありそうです.

2021年7月16日金曜日

WSL上のConcourse CIで, Unreal Engine 4のビルドがしたい

はじめに

CI/CD環境の構築が属人化するなら, もう私が扱いやすい環境があればいいのではないか?, ということで脱Jenkinsを行い, ConcourseでどうしてもUE4のビルドを自動化したいです. WSLやWSL上のDockerの構築については省略します.

Jenkins

Jenkinsではだめなのかというと, 扱い辛いからです. よく属人化すると言われますが, その理由を説明した資料を私は知りません. 私のまわりでは次の理由だと思います.

  • 不安定
    • 全く設定を変更していないつもりでもビルドが壊れる
  • 設定が難しい
    • パイプライン追加以前では, VCSで管理したり, 再利用しようとするとシェルスクリプトやバッチファイルにするしかなかった. 少し高級なcronでしかなかった
      • シェルスクリプトやバッチファイルに詳しい人に依存する
    • パイプラインは, GroovyのDSLでわかりにくい
      • 他に役に立たないDSLを勉強したくない, ドキュメントもわかり辛い
      • DSLなのでJenkins上でしか実行できない. パイプラインを書いてコミットしてJenkins上で実行して失敗の繰り返し, 苦痛でしかない
  • CI/CDの重要性に興味・理解ある人しか, 修正・改善をしない
    • どんなツールを使ってもこのために属人化する

WSL

WSLである理由は環境移行が楽かもしれないということです. 今日の企業ではレンタルPCで社員の環境を作ることが多く, ビルドマシンも同じくレンタルPCが多いです. それほど頻繁ではないですが, レンタル期間終了とともに環境移行を強いられます. 以前にWindows上のVM環境にビルド環境を構築して移行を楽にしようと頑張りましたが失敗しました. 原因はファイルシステムのアクセスです. VMからはともかく, CI/CDツール越しではうまくいきませんでした. WSLならもう少し楽になるのでは?

UE4のビルド

Windows向けビルドしか試していませんが, RunUAT.batが呼び出せれば大体解決しそうです.

Concourse CI インストール

鍵生成

まず, コンコースのサーバ・クライアント・ユーティリティを兼ねたバイナリを取得します. このバイナリさえあればDockerは必要ないのですが, DBの構築も面倒なので, このバイナリは鍵生成だけに使います.

$curl -OL https://github.com/concourse/concourse/releases/download/vX.X.X/concou$rse-X.X.X-linux-amd64.tgz
$tar zxvf concourse-X.X.X-linux-amd64.tgz

バイナリを取得できたら鍵を生成します. ポイントはワーカの公開鍵を別名でコピーしている部分です.

$mkdir -p keys/web keys/worker
$./concourse/bin/concourse generate-key -t ssh -f ./tsa_host_key
$./concourse/bin/concourse generate-key -t ssh -f ./worker_key

$cp ./worker_key.pub ./keys/web/authorized_worker_keys

$mv ./tsa_host_key ./keys/web/
$mv ./worker_key ./keys/worker/
$mv ./tsa_host_key.pub ./keys/worker/
$mv ./worker_key.pub ./keys/web/ 

Docker-compose

docker-compose.ymlを作成します.

docker-compose.yml
version: '3'

services:
  concourse-db:
    image: postgres
    container_name: concourse-db
    environment:
      POSTGRES_DB: concourse
      POSTGRES_PASSWORD: concourse_pass
      POSTGRES_USER: concourse_user
      PGDATA: /var/lib/postgresql/data/pgdata
    volumes:
      - ./db/postgres:/var/lib/postgresql/data
      - ./db/logs:/var/log

  concourse:
    image: concourse/concourse
    container_name: concourse
    restart: unless-stopped
    command: web
    privileged: true
    depends_on: [concourse-db]
    ports: ["8000:8080", "2222:2222"]
    volumes: ["./keys/web:/concourse-keys"]
    environment:
      CONCOURSE_POSTGRES_HOST: concourse-db
      CONCOURSE_POSTGRES_USER: concourse_user
      CONCOURSE_POSTGRES_PASSWORD: concourse_pass
      CONCOURSE_POSTGRES_DATABASE: concourse
      CONCOURSE_EXTERNAL_URL: http://localhost:8000
      CONCOURSE_ADD_LOCAL_USER: admin:admin
      CONCOURSE_MAIN_TEAM_LOCAL_USER: admin
      CONCOURSE_WORKER_BAGGAGECLAIM_DRIVER: overlay
      
  concourse-worker:
    image: concourse/concourse
    privileged: true
    links: [concourse]
    depends_on: [concourse]
    command: worker
    volumes: ["./keys/worker:/concourse-keys"]
    environment:
      CONCOURSE_TSA_HOST: concourse:2222

Windowsのワーカ

これが重要です. WSL上のシェルからなんとかできるかと試行錯誤しましたが, 妥協してWindows上でワーカを動かす方が楽でした. Windows用のconcourseバイナリを取得して起動するだけです.

concourse worker --work-dir ./work --tsa-host localhost:2222 --tsa-public-key ./keys/worker/tsa_host_key.pub --tsa-worker-private-key ./keys/worker/worker_key

プロジェクト管理

targetはサーバに対応します. 1サーバで複数プロジェクトを管理するなら, チームを使用します.

fly -t server_name set-team --team-name project_name --local-user user_name

ログインは, -nでチーム名を指定します.

fly -t server_name login -n project_name -u user_name -p user_pass

ビルド

最も単純なビルド設定は次のようになります. 結局, バッチファイルに行きついていますが, バッチファイルの引数である程度柔軟にできると思います.

jobs:
  - name: build_quickstart
    plan:
      - task: build
        config:
          platform: windows
          run:
            path: cmd.exe
            args: ["/c", "chcp 65001 & cd /d ((PROJECT_ROOT)) & call build.bat"]

パラメータ((PROJECT_ROOT))は別のファイルenvironment.ymlで定義しています.

PROJECT_ROOT: "X:/Path to Unreal Project"

パイプライン設定時に-lオプションでパラメータ設定を指定します.

$ fly -t main sp -p build -c build.yml -l environment.yml

build.batも一応書いておきます, environment.batはRunUAT.batのパスを設定しているだけです.

call environment.bat
%UNREAL_RUNUAT% BuildCookRun -project=%~dp0/project.uproject -build -cook -stage -allmap -pak -nop4 -partialgc -platform=Win64 -clientconfig=Development

DebianでDockerサービスが起動に失敗する

DockerがiptablesでNATの設定をしようとするが, Debianは別のソフトウェアでNATを設定しているので失敗する, でいいのでしょうか. 

Docker forum 

sudo update-alternatives --set iptables /usr/sbin/iptables-legacy
sudo update-alternatives --set ip6tables /usr/sbin/ip6tables-legacy

2021年6月17日木曜日

Pimplはアンチパターンだと思います

はじめに

数年前は使うこともあったのですが, 現代にはふさわしくないと思い使わなくなりました.

利点と欠点, それについての考え

利点

  • includeを減らして, コンパイル時間の短縮
    • 2021年では, 計算機, コンパイラ, そしてリンカの性能が向上しました. これは使う理由にはなりません. 聞こえていますか?20年前から来たあなた
      • 時間は金で買うべきです, ビルドマシンぐらい金をかけましょう
    • 今のプロジェクトのビルドが遅い理由は, 次です. ビルドが遅すぎて, ビルドは一日一回, agileではなく, sluggishです, stupidプロジェクトでもいいです
      • Pimplを数多く使っているのに, includeが多い. コピペのせいもあるのですが
        • リファクタリングをしないので, コピペが修正されることは2度とない
      • inlineが多い
        • inlineを理解していない
        • コンパイラオプションで, できるだけinline展開するようにしている
        • inline展開で処理が速くなるとは限らない, これは今も昔も
      • コンパイラオプションで最大限の最適化を設定している
        • O2より上は速くなるかは環境依存, 遅くなることはよくある
          • 使用者が少ないので, 不具合も多くなる
        • コンパイラを理解していない
  • 実装の隠蔽
    • 例えば, JavaやC#で困ったことはありますか?
      • 自分の意に沿わないからといって, ヘッダを書き換えるようなエンジニア?をチームに置いておきますか? そちらの方が問題だと思います
    • インターフェイスを使って, FILEのようなことをすれば完全に隠蔽できるので, 使う理由にはなりません

欠点

  • メモリコストと実行速度に悪影響がある
    • 処理落ちがどうのなど, 言っていることとやっていることが異なる
  • 冗長
    • 処理を転送するだけの記述がコード量を増やす
    • コードを追うことに2倍のコストがかかる
    • たまにインターフェイスのメソッド名と, 実体のメソッド名が異なる
      • ガンジーでも助走付けて
  • ヘビークラスを作りやすい
    • これは当社比なのですが, 10年以上のエンジニア経験では, Pimplイディオムはくそでかクラスになりやすい傾向にあります
      • コンパイル時間の短縮という錦の旗, メモリコストと実行速度を考えると, Pimplイディオムがコンポジションに向いていないことが原因と思っています
    • コンポジションやアグリゲーションで, ソフトウェアを建築する, という考え方を持っている人には受け入れがたいです

まとめ

他人に強制するつもりはありませんが, 意味のないイディオムだと思います. 

2021年6月10日木曜日

Windows 10 のシステムロケールの不具合

どの更新からか, Windows 10のシステムロケールに, "ベータ: ワールドワイド言語サポートでUnicode UTF-8を使用(U)"というチェックが追加された. デフォルトでONなのですが, これのせいで文字化けするアプリケーションが出てきた. 少しテストすればわかりそうなものですが.

2021年5月3日月曜日

-marchのx86-64向け, CPU命令世代オプション

GCC 11.0から, LLVM 12.0から, -marchオプションにx86-64用のCPU命令世代指定が追加された. -march=x86-64-v[234]のように, 命令セットを対象に, ある程度の範囲で絞った世代に分割して指定することができる. これまで, -march=nativeとしてコンパイルしたCPUに合わせるか, -march=skylakeなどのCPUを固定する方法しかなかった.

CPUベンダとしては, 新CPUごとに新しい命令を追加してアピールしたい. 開発者としては, ある程度古いCPUもサポートしながら, 新しい命令も使いたい. このふたつの間を埋める機能といえます. 開発者が, ある命令セットがどのCPUからサポートしているのか, 把握して管理することは手間がかかります.

オプション 有効になる命令 CPU世代
x86-64 CMOV, CMPXCHG8B, FPU, FXSR, MMX, FXSR, SCE, SSE, SSE2 Pentium 4
x86-64-v2 CMPXCHG16B, LAHF-SAHF, POPCNT, SSE3, SSE4.1, SSE4.2, SSSE3 Nehalem
x86-64-v3 AVX, AVX2, BMI1, BMI2, F16C, FMA, LZCNT, MOVBE, XSAVE Haswell
x86-64-v4 AVX512F, AVX512BW, AVX512CD, AVX512DQ, AVX512VL Skylake Xeon

2021年3月13日土曜日

チケットの書き方

はじめに

この文書は, 最低限伝わるのチケットの書き方を, 同僚に身に着けてもらうことを目的にしています. その方法は, 読者が容易に理解できる文書を書くように心がけ, 振り返って改善を継続することです.

チケットはチームの資産です. 常に自分が作成したチケットについて, 内容が読者に理解しやすかったかを振り返り, 次の機会に改善することが重要です. 初めから完璧な文書を作成できる人などいないですし, 誰が書いた文書も常に足りていません. 伝わる文書, 伝わった文書, 伝わったからいいやの文書, それぞれ異なります.

他人が作成した, 理解が難しいチケットを修正してはいけない, という法はありません. より上手くチームが動けるように改善すべきです. 自分が作成したチケットが修正されたなら, それは学ぶ機会に恵まれたということです.

チケットは, タスク管理システムやイシュー管理システムにおける, 一つのタスクやイシューを管理するための一連の情報を言います. チケットの概念の名称はシステムによって異なるため, 読み替えてください.

チケットの文書

チケットの文書は読者に内容を理解してもらうためのものです. 自分のToDo用のチケットというものがあるかもしれません. それをチームのシステム上に作成する理由は, 他人が読むことを前提としているはずです. 本当に私的ToDoなら, 自分でシステムを立て, そこに書くべきです. チームの場と私の場を混同してはいけません.

内容

チケットの文書では, ひとつの主題に集中します. そして, ひとつの主題について, 事実や状況といった情報と意見を正確にもれなく簡潔に記述します. 感想などの心情的要素を書きません. 情報の内容は, 主題(文書の目的)と読者の要求によって変わりますが, 意見との区別を明確にします. 事実は, あいまいな表現や主観に依存する形容詞を使わず, できるだけ明確に記述します. 意見は, 事実の上に立ち, 論理的に導き出した結果です. 意見の記述は複数の評価が並立しますが, 読者が記述された事実から評価できる必要があります.

事実と状況

事実と実際に起きた状況だけを正確に記述します. 意見とは言えない, 論理的理由のない憶測は無視されるため書かない方がいいです. 結果的にその憶測が当たったとしても偶然です, タスクの担当者は参考にしていません.

私がよく見る憶測の文章は, 次のようなものです. 憶測に時間を費やす必要はありません, あなたの仕事に時間を使ってください.

× おそらく, 〇〇〇が原因な気がする

曖昧な表現

■ たぶん, らしい, かもしれない, と思う

事実かどうか確認してから書くようにします.

タスクでは手順を追加することになります. 手順の粒度が大きい場合, 別タスクになることもあります.

たぶん, 〇〇〇の方が有効だと思います. △△△という方法で確認してみます.

イシューでは再現できなかった, 再現のために試行する時間がないこともあると思います. その場合はそのまま書けばいいです.

〇〇〇という手順で, 3/10で再現しました

〇〇〇を試しましたが, 再現できませんでした

再現するかは試していません

会話では, 次のように曖昧な表現を使ってしまった時に修正します.

たぶん, 〇〇〇だと思います. 少し待ってください, 確認します.

■ 擬音語, 擬態語

その意味や度合いは個人の心情に依存します, 絶対に使わないようにします.

× バーンと表示してほしい

× ビャーと出てくる

× ドーンって感じで

言葉の選択

誰でも理解できる言葉を選択します. 一般的にチーム人員は変わるものです. 未来の見知らぬチームメンバが理解できるように書けばいいです. 指しているものが変わる可能性がある言葉, あれ, それ, は絶対に使わないようにします. バージョンを表す, 最新版, 最新の, も使ってはいけません.
余談ですが, 聞き手が理解できないことを解った上で, 特定コミュニティだけで通じる言葉を使う同僚がいます.

簡潔な文書

英国首相であった, ウィンストン・レナード・スペンサー・チャーチルは ([1],[2],[4]),

われわれの職務を遂行するには大量の書類を読まねばならぬ。その書類のほとんど全てが長すぎる。時間が無駄だし、要点をみつけるのに手間がかかる。同僚諸兄とその部下の方々に、報告書をもっと短くするようにご配意願いたい。

という書簡を部下に送ったそうです. 読解に時間がかかる文書は, 他人に時間を浪費させています.

特に過度な敬語は無駄です. もし, チケットに過度な敬語を使う必要があるならば, チームビルドに失敗しています. チームメンバの関係を修復すべきです.

チケットの書き方

共通

会話をしない

会話は口頭やチャットツールで行います. その会話の中で決まったこと, 補足すべき事項をチケットにまとめます. チャットツールは記録を保存する目的には向いていません. 会話のやりとりで, 相手が理解した・確認が取れた, と思い込んではいけません.
チケットはチームで解決することについて書きます. 誰か特定の人にお願いするのではなく, 全員で解決するものです.

× タイトル:〇〇〇をお願いします

タスク

次の4つを書くといいです, 全てを書く必要はありません.

  • 目的
    • どうしてそれを行うのか
    • 次の手段を検討・再考することにつながる, 重要な項目です
      • 副次目的があれば, 優先順位をつけて, 書いておくといいです
      • 機能を削らなければときの判断材料です
  • 手段・手順
    • 目的を実現する手順です
    • 機能を削る場合に変更されます
  • 目標
    • 目的が達成されたかどうか判定するための材料です
    • 数値で表現できる方がいいですが, 主観に依存することも多いです
    • 具体的成果物でもいいです. できれば成果物の品質も数値で表現できるほうがいいです
  • 完了条件
    • 目標に到達したかどうかが基本ですので, 目標と混ぜて記述してもいいです
    • 完了条件と目標がずれていた場合, 目的の設定がおかしい可能性が高いです

バグ

  • 状況
    • いつ, どこで, 何をしたか
      • ソフトウェアにおいては, これは一体なことが多いです
      • ゲームなどの場合, 何をしたかと不具合発生のタイミングが対応しない場合があります
      • 真に正確であることではなく, 観測された事実であることが大事です

〇〇〇画面で, △△△したときに

〇〇〇画面で, △△△していたときに

  • 期待される状態

    • 仕様で決めた状態
    • 一般的に望ましいと思われる状態
      • 仕様の不具合を含めて見直しをする必要があります
  • 再現手順

    • あればいいが, 再現するために過度な時間を費やす必要はないです
    • 憶測は書いてはいけません

参考までに, エンジニアの手順を示します.

  1. 再現して, 確かに起きることを確認します
    • 100%再現できる状態を探します. プログラムの原理的にこれは必ず存在します
      • ハードウェアや宇宙線によるビット破壊は考慮しません
      • 外部モジュールが原因の場合は, 全く別の解決方法になります
  2. 不具合が発生した瞬間に実行されていたプログラム片を特定します
    • そこで実行されていた命令か, 使用していたデータのどちらか, または両方に原因があります
  3. 原因を特定して修正します
  4. 1.で特定した再現手順で不具合が起きないことを確認します
    • 原因によって, 影響がある範囲も不具合が起きないことを確認します
    • ログやアサーションなど, 同じ不具合が起きた場合に検出できる仕組みを導入します

まとめ

あなたの読者が内容を理解できるか? それだけです. そのために改善を継続します.

最初から誰に対しても厳格にする必要はありません, より良い状態に改善していけばいいだけです.

〇〇〇画面がおかしい

というタイトルのチケットを回されたら, エンジニアが修正すればいいだけです. 時にはチケット上で会話することもあるでしょう. 方法に縛られる必要はありません.

正しく動作することを確認しました. 修正ありがとうございます. クローズします.

参考文献

  • [1] 木下 是雄,「理科系の作文技術」,1981
  • [2] 木下 是雄,久間月 慧太郎,「まんがでわかる 理科系の作文技術」,2018
  • [3] Barbara Minto,山崎 康司,「新版 考える技術・書く技術」,1999
  • [4] https://studying.jp/engineer/blog/20191226.html

2020年1月12日日曜日

ポータブル Vim

動機

Windows用のポータブルなエディタを用意したい.
ミーティング等でノートをとるときなどに使用したい.

  • ネットワークドライブ越しで使える
  • 簡単にコピーできるようにサイズが小さい
  • テキストエディタの機能だけでよい

Vim

Kaoriya版をベースにする.
vim.exe, gvim.exeの不要な方を削除する.

まず, HOMEの設定をしなければいけないため, vimrc_local.vimで設定する.

let $HOME=expand('%:p:h')

_vimrc, _gvimrcをvimrc, gvimrcの後にロードするため, ここに設定を書く.

プラグイン無効化

vimrcに以下を追加

let plugin_autodate_disable  = 1
let plugin_cmdex_disable     = 1
let plugin_dicwin_disable    = 1
let plugin_format_disable    = 1
let plugin_hz_ja_disable     = 1
let plugin_scrnmode_disable  = 1

vimdoc-jaも無効化して, plugins\vimdoc-jaを削除する.

プラグインインストール

必要なものは手動で行う.

フォント

見やすくないがWindows 7が全て駆逐されるまでは,

set guifont=MS_Mincho:h12:cSHIFTJIS

2019年8月2日金曜日

SIGGRAPH 2019 Ray Tracing Roundup

http://www.realtimerendering.com/raytracing/roundup.html

2019年1月20日日曜日

PlantUML

インストール

PlantUMLから, plantuml.jarをダウンロードします.
また, Graphvizもダウンロードしておきます.

Windowsの場合以下のようなバッチを用意します.
plantuml.bat
@set GRAPHVIZ_DOT=<path to graphviz>\bin\dot.exe
@<path to JDK>\bin\java.exe -jar <path to PlantUML>\plantuml.jar -config config.txt -charset UTF-8 %*
設定ファイルでフォントサイズなどを設定します.
クラス図のアイコンは非表示にしました.
config.txt
skinparam classArrowFontSize 14
skinparam classAttributeFontSize 14
skinparam classFontSize 16
skinparam classStereotypeFontSize 16
skinparam classAttributeIconSize 0

2018年6月13日水曜日

Real-Time Rendering, Fourth Edition

Real-Time Renderingの第4版が8月発売です。
Real-Time Rendering, Fourth Edition

2018年2月19日月曜日

VinoでVNC

XubuntuでVNCサーバを設定するノート

VNCサーバ

vinoをインストールする.
#vino-preferences
で設定起動.
以下のチェックを入れる.
[Sharing]
Allow other users to view your desktop
 Allow other users to control your desktop

以下のチェックを外す.
[Security]
You must confirm each access to this machine

暗号化を使わない場合,
#gsettings set org.gnome.Vino require-encryption false
とする.
サーバーの場所は以下,
#/usr/lib/vino/vino-server
スタートアップに設定しておくと楽.
VNCクライアントからは, IPアドレス:ディスプレイ番号で接続する. ディスプレイ番号が0なら省略可能.

Wake On LAN

まず, BIOS設定からそれっぽいものを有効にする.
ethtoolをインストールして, ツールにインターフェイス名を指定して情報を表示する.
以下のように, ステータスがdになっていれば無効になっている.
#apt install ethtool
#ethtool enp1s0
    ----
    Wake-on: d
    ----
以下のように有効化, 必要なら適当な箇所で有効になるように設定する.
ステータスがgになっていれば有効.
#ethtool -s enp1s0 wol g
    ----
    Wake-on: g
    ----

.Netから叩き起こす
using System.IO;
using System.Net;
using System.Net.NetworkInformation;
using System.Net.Sockets;

namespace WakeOnLAN
{
    class Program
    {
        static void Main(string[] args)
        {
            if(args.Length<2) {
                System.Console.WriteLine("Usage: <global ip address> <mac address>");
                return;
            }
            try {
                IPAddress globalAddress = null;
                if(!IPAddress.TryParse(args[0], out globalAddress)) {
                    return;
                }
                PhysicalAddress physicalAddress = PhysicalAddress.Parse(args[1]);
                using(MemoryStream memoryStream = new MemoryStream())
                using(BinaryWriter binaryWriter = new BinaryWriter(memoryStream))
                using(UdpClient client = new UdpClient()) {
                    for(int i = 0; i<6; ++i) {
                        binaryWriter.Write((byte)0xFF);
                    }
                    byte[] bytes = physicalAddress.GetAddressBytes();
                    for(int i = 0; i<16; ++i) {
                        binaryWriter.Write(bytes);
                    }

                    binaryWriter.Flush();
                    byte[] sendData = memoryStream.ToArray();
                    client.EnableBroadcast = true;
                    client.Send(sendData, sendData.Length, new IPEndPoint(globalAddress, 0));
                    client.Close();
                }

            } catch {
                return;
            }
        }
    }
}