去年も ふりかえり だけはしていたので今年も。
自炊率が圧倒的に下がった。 週に多くても土日の夕飯を作って2回とか。
バリエーションは オムライス/鯖バーグ/野菜炒め/焼きそば
。
いろいろやっていた。 相変わらずWebぽくない案件が多い. C++
を書く機会が一番多かった気がする。
かといって、特に C++ に詳しくなれた気もしないけれど。
相変わらず労働環境も良い。
貯金も少し増えてきたために財布の紐が緩くなって、去年比で見ると出費が増えている気もする。
先月の電気代が15000円で驚いた。電気代は暖房機の消し忘れが複数回起こったことによるものだけれど。
animetick
で視聴管理をしているので、それで確認した。
各年の視聴本数(完走数)を数えてみる(分割Nクールは分割毎に1本とカウント)と以下のようになった。
だいたい平均して各期10本くらい視聴していた。
2015年の個人的なベストは のんのんびより(2期)
。
劇伴、合間合間のギャグ、キャラクター、OP/ED などいろいろなものがほぼ自分好みなので見ていて気持ちよかった。
BOXが出たら買います。
ちなみに2014年は ばらかもん
。
スクリプト言語による効率的ゲーム開発 C/C++へのLua組込み実践 という本を買っていたので、
この本を読みつつ、去年は Lua
をやろうとしたが、あまり書けなかった。
Lua を書く機会が何度かあったけど、最終的には他の言語で書いてた記憶がある。 スクリプトから少し重たい外部コマンドを複数回実行などして その結果を加工するような用途の時に使ってみたけど、そのケースでは外部コマンドの起動オーバーヘッドが ruby と比較してかなり大きくてダメだった。最終的に go に置き換えたりしたし。
そのせいもあって、昔は Lua が最も高速なスクリプト言語である、という文言をよく見た気がしたけど ruby と比較してそこまで早くないなぁと思った。
C++のアプリケーションからLuaのスクリプトをリロードして動作を変えるのはやってて面白かった、というより爽快だった。 コンパイルしないのは最高。
読んだ本
読んでる途中の本/積んでる本
最近肩とか腰とか痛いので、すこやかににすごしたい。
当日は別の遊ぶ予定があったが無理やり数十分くらい時間をもらって参加したのだけど 満足に1つも解けず…。
もうちょっとやるならやるでちゃんと時間をとってやるべきだった( ;´Д`)
本戦がかなり難しかったらしく面白そうだが、そもそも自分からしたら予選で難しいので、予選を解いてみた
300x300のセルが与えられて、各セルに整数(負数を含む)が与えられており、 セルの中で長方形を二つ選んだ時に、各長方形の整数の和が最大になるように選ぶ問題。
簡単に考えられるのは事前に各行/各列で累積和を計算しておいて、あとは長方形を全列挙するという
方針の解き方で累積和の計算に O(H*W)
、長方形の列挙に O(H^2*W^2)
あとは二つ選ばないといけないので、組み合わせを試すために列挙した長方形の端っこの x座標とy座標とコストのペアを覚えておいて重ならないように組み合わせを試した
http://dwango2016-prelims.contest.atcoder.jp/submissions/632337
で、結局 O(H^2 *W^2)
がとれないので解説を読む。
O(H * W^2)
でコスト最大の長方形を探索するが、その際にx座標でどこからどこまでの情報とコストのペアが
得られるので、(x座標で見て)重ならない組み合わせが列挙できて、あとはセルを転置して同じことをする、だった
http://dwango2016-prelims.contest.atcoder.jp/submissions/637939
ちょっと前に OpenH264 というエンコーダに小さなプルリクを出した時のメモが以下のように今も残ってた。
この Mac のデフォルトのメモ帳は要素を増やすとそれなりに動作が緩慢になっていくので消そうと思ったけど ただ消すのも忍びないので書き残しておくことにした。
メモでは色々調べていたけど、作業的には 小さなもの だった。
ことの発端としてはこういうサイト を見ながら、小さなSIMDプログラムを書く機会があったが、本当に小さくてすぐ終わってしまったので 他にも何かしらで書けないかと考えた時についでにOSSにプルリク投げてみるか、という機運が高まったことから始まった。 最終的にSIMDコード書けてないわけだけど…。
さらに、SIMDは intrinsics
で書きたかったのだけれど、
SIMDはどこもアセンブラで、メモを見返してみるとアセンブラについて調べた部分がいくらかあった。
書いてて思い出してきたが AVX2の開発も受け付けてるという記述があり、書こうと思ったら そもそもAVX2がプログラム内で有効であるか検出する機構がないので、とりあえずそれを書いたという流れだったと思う。
コミットログを眺めてみたけどぱっと見AVX2コードは入ってなさそう。今はあんまりやる気がない..。
もう書くことがないので、あとはつらつらメモの残りを羅列することにする。 プロジェクトを何も知らない人が読んでも意味がわからず、メモ同士の関連性も低く 本当に有用にするには補助的な文章が必要だろうけど面倒くさいのでしない。
あと、ここに書いてあることの正しさは保証してませんので予めご了承。
空っぽのクラス。抽象クラス。
具象クラスは CWelsH264SVCEncoder
になる。メインのでかいクラス。
WelsCreateSVCEncoder() は encoder/plus/src/welsEncoderExt.cpp にある。
codec/console/enc/src/welsenc.cpp にコンソール版の main() がある。
EncodeFrameInternalを呼び出す。入力がI420じゃない場合は中断。
メインな関数。色々呼び出す。分かったものだけ記述。
フレームタイプを決定する。x264にも似た名前の関数があるけど、x264と違ってここから探索が発生することはなさそう
svc_motion_estimate.cpp:WelsMotionEstimateSearch[Static|Scrolled]
encoder_ext において pFuncList->pfMotionSearch に代入されている。
代入後 core/src/svc_base_layer_md
で利用されている。
WelsMotionEstimateSearch は内部で pFuncList->pfCalculateSatd を呼び出す
core/src/sample:WelsInitSampleSadFunc
で設定読む上で気をつけたこと。
セミコロンの前の文字はよく命令の suffix についている。
mov[d|q|dqa|dqu|sxd]
lea
アドレス計算命令。フラグレジスタが変更されない。アドレス自体の演算に利用。
pxor
ビット単位の xor を実行。オペランドには 64bit同士、128bit同士を指定することができる。
psub[b|w|d]
オペランドに64bit同士、128bit同士をとれる。 suffix がそれぞれ byte, word, double-word を指すので 8bit/16bit/32bit スロットでの演算となる。
pmax[s|u][|b|w|d]
レジスタを2つとり、スロット毎に比較して最大値を格納する。 値を評価する場合に符号あり・なしとスロットの大きさで命令が分かれる。
psadbw
符号なし8bit整数で絶対値誤差の合計値を計算して格納レジスタの下位16bitに書き込む。 オペランドに64bit/128bitレジスタ同士を取る。
shufps
名前的にはシャッフルを押すほどのシャッフルでもないけど確かにシャッフル可能な命令。 オペランドを3つとり(うちSIMDレジスタが2つ)、スロットを32bitで評価してそれぞれの SIMDレジスタから2つのスロットを格納先へ書き込む。
pmaddubsw
Multiply-ADD Unsigned Byte, Signed Word
乗算はオペランドレジスタを符号なし8bit整数スロットで評価し、 次のオペランドレジスタは符号あり8bitで評価。 乗算の結果を2つずつ和にして16bitスロットとして格納先レジスタへ書き込む。
movehl_ps
各 hi-64bit を2つのSIMDレジスタからとって merge。
用いられているアセンブラ。
codec/common/x86/inc_asm.asm に共通マクロがある。
わかったものだけ。
あんまり調べてない。
WelsSampleSadFourWxH
4つ分計算する。この4つ分は上下左右の1pixelだけずれたものを計算している。
WelsSampleSad4x4_mmx
ナイーブに実装されている。mmxなのでレジスタ長が64bitなので8bit*8で2line分まで入るので よしなにロードして2回 psadbw するだけ。
WelsSampleSad16x16_sse2
128bitSAD命令で 4x16 を4回呼ぶ構成。
codec/common/x86/satd_sad.asm
例によって、連休中は記事にまとめることにする。
基本的に、あまり外出の予定はない。
前日の飲み会で久しぶりにお酒を沢山飲んだせいなのか、 昼頃起きてから頭痛がひどくて基本的に動きたくなかったし動けなかった。
が、前日まで同期を家に泊めていたので、それらの片付けとか部屋の掃除とかをした。
http://mtgwiki.com/wiki/ブースタードラフト
これで遊んでた。6時間くらい。
オブジェクト指向入門 第2版 方法論・実践 を少し読んでは寝てを繰り返してた。
同期に誘われて買い物に出かける。少し高い(4kくらい)ドライヤーを買った。 ドライヤーの風速が2倍弱くらいになってだいぶ髪が乾くのが早くなって良い感じ。
朝飯にオムライスを作る。
メイヤー本を読み進める。やっと300/800ページくらいまで進んだ。連休中の目標としてはなんとか読み終えたいと思っていた。 これが読み終わると積んでる紙の技術書がなくなるので kindle と iPad air2 を買って電子書籍に移行したい。
openh264のコードリーディングをする。ビルドして出来た実行バイナリでYUVファイルをエンコードしてみようと思ったけど なんかうまくコマンドラインオプションがパースされない。コンフィングファイルでオプション値指定をやってもうまくいかない。エンコード結果がおかしくなる。 なぜか出力解像度が縦横半分くらいになってしまう。それにオプションがx264と互換性がない(当たり前だけど.)し細かいのでよくわからない。
最終的に vagrant
で Ubuntu を用意して Qiitaにあるやり方で ffmpeg に組み込んだ形でなんとか普通のエンコードができた。
と思ってたけど、コンフィグファイルのやり方で普通にエンコードできた。LayerCfg
で”layer”(よくわからない概念)用のcfgファイルも用意して動いた。でもなんかフレームレートがおかしい。
具合があまり良くないので多分横になってた時間が長かった。気がする。
AtCoder Regular Contest 038
に参加したけど1問しか解けなかった。
解き直した。ゲーム系の問題の解き方が良くわかってなかった。Grundy数の「今の状態から一手で行ける状態のGrundy数に含まれていない最小の非不の整数が 今の状態のGrundy数」っていうのややこしいけどわかった気がする。
覚えてない..
結果 o o - -
提出 url
両端から1文字ずつ付き合わせていって4パターンで分岐。
文字列長が奇数なら真ん中を省く。
貪欲にTiの小さいものから処理する。
実際にシミュレーションしてペナルティを計算する。
あとは階上どうしの掛け算をする。剰余の分配法則的なものはあまり知らないけど
これで問題なかった。
最初のワーシャルフロイドはOKだけど、クエリ毎に打つことはできなくて けどO(V^2)でテーブル更新可能だった。解説スライドでたしかにという感じだった。気づかなかった。
無駄にワーシャルフロイドと更新部分のループをSIMDで描いたら200msくらい早くなった。
この記事にもあるように
intrinsicsはSSE2まで使えるぽい。例にならってSSE4.1の_mm_min_epi32
の代わりをインラインアセンブラで書いた。
AtCoder環境はどのバージョンのSIMDまでサポートしてるんだろう。
実際の値はいらないけどに大小比較をする場合は log が使えることを知った。
あと log(a*b)=log(a)+log(b)
log(a/b)=log(a)-log(b)
とか久しぶりだった。
BITの更新をするときに変位を足すのではなくて任意の値にしたい場合は負の加算でリセットすることでなんとかなることを知った。