1 ヒント集
2==========
3(とどのつまり便利な可能性が微粒子レベルで存在するドキュメント)
4
5
6 v1.0.0(画像分割処理無し)でのメモリ最大消費量の計算式
7------------------------------------------------------
8但し、これは変換処理のみのメモリ最大消費量の計算なので、実際には入力データのピクセル数に比例する中間表現保持のコスト等もかかります。
9
10 * w : 画像幅
11 * h : 画像高
12 * bitDepth = 32 : 1px当たりのbit数
13 * maxNInputAndOutputPlane = 256 : モデル1階層で取り扱う「入力平面と出力平面の合計値」の最大数
14
15以上の変数設定で表現される計算式は以下のとおりです。
16
17### ノイズ除去時
18
19 (`bitDepth` / 8) * w * h * `maxNInputAndOutputPlane`
20
21 = 1024 * w * h (bite)
22
23 = w * h (KiB)
24
25### 2倍拡大時
26
27 (`bitDepth` / 8) * (w * 2) * (h * 2) * `maxNInputAndOutputPlane`
28
29 = 1024 * 4 * w * h (bite)
30
31 = 4 * w * h (KiB)
32
33従って、wやhが1024以上だと、単位が1つずつ上がります。
34
35
36 v1.1.0(画像分割処理有り)でのメモリ最大消費量
37----------------------------------------------
38
391つの処理(モデル7層の畳み込みとLeakyReLU)でのメモリ最大消費量は、ブロックサイズを 2^9 x 2^9 = 512x512 に設定しているので、256MiB(中間表現で消費される分を除く)が最大消費量になる。
40
41
42 画像分割処理についてのメモ
43----------------------------
44自分用なので、一応載せておきますがちょっとわかりづらいです。
45(master最新コミットで実装済み)
46
47  * 画像を分割する際、上下左右7px分余計に含むように分割する。
48    (畳み込み演算の仕様上、7層の畳み込み後は画像の周囲7px分は使用不可(invalid)な値になってしまうため)
49    (上下左右7px取っておけば、そのパディング以外の部分は一括処理と変わらない結果が得られるはず)
50  * 画像端は予め画像端複製モードで7pxパディングしておく(copyMakeBorder関数で可能らしい)
51
52  * 分割後の大きさは、恐らく2の累乗のサイズになっているのが望ましいと思われる
53    (つまり、1ブロックがカバーできるのはw = h = 2^n - 14までであると考えられる)
54  * 1ブロックのサイズ : 4 x 2^2n bite
55  * 1ブロック処理中の最大メモリ消費量(予測値) : ((blockBite)) x 256 bite = 2^2n KiB
56  * 同時処理スレッドを4と仮定した上で、最大メモリ消費量が4GiBを越えないようにするには、
57    ブロックサイズは w = h = 2^9 = 512 までとなる(絶対に上の計算値よりもメモリを消費するので、2^10にするべきではない)
58      - ブロックサイズの累乗数n = 9であれば、1平面のサイズはブロックサイズと同じ 2^20 bite = 1MiB になるので、グラフィックボードのメモリには必ず収まる。
59
60  * 先にブロックサイズの1辺の長さの倍数に、入力画像にパディングを入れておく(右下方向に余計に入れることで調整)
61  * その後、全ての処理が終わり出力平面の貼りあわせが終わったら、そのパディングを含まない領域を最終出力平面にコピーする。
62
63  * 入力平面の分割の際の座標計算と出力平面の張り合わせの際の貼り合わせ方は、要検討。
64
65
66 GPU利用メモ
67-------------
68
69 * 一旦全ての入力平面・処理中モデルのカーネルをGPUに読み込み、全てGPU上でやらせて出力平面も一旦全てGPU上に持つようにすると速い?
70 * OpenCLには`float3`、`float32`といった、専用のベクトル変数が用意されている。これを利用し、入力平面・カーネルの同じインデックスにある値をベクトル化し、ベクトル要素毎の掛け算や足し算を実行すれば、例えば`float32`を使用すれば、32個分の出力平面生成処理を1回の繰り返しで終わらせることが出来る(と思われる)。
71 * cv::filter2Dにはマルチチャンネルのサポートが無いので、これをやるなら恐らく自分でOpenCLカーネルを書く必要がある。
72 * そもそもcv::filter2DのOCL実装は、値がそれぞれ異なる多数のカーネルを畳み込みすることに対して非常に弱い(異なるカーネルを投入する毎にOCLプログラムのコンパイルが走ってしまう)。従って、SpatialConvolutionの実装は自前のOCLカーネルでやった方が恐らく良い。
73 * OpenCVがインクルードしているOpenCLヘッダのバージョンが1.2なので、これに実際に使用されるOpenCLデバイスが従うとすると、ベクトル変数の最大長は`16`っぽい。
74
75
76 アルファチャンネルの取り扱いについて
77--------------------------------------
78
79 * 基本的には、チャンネルスプリットをかけてAチャンネルだけ別に保持しておき、それを従来手法(bicubic or lanczos4)で拡大して、最後に結合すれば良いと考えられるが、モデルによる補正は線を変更してしまうため、ちゃんとした出力にならない可能性がある。
80 * アルファチャンネルもモデルを使用して拡大する、という方法も考えられるには考えられるが、これも結合後にちゃんとした出力になるかは分からない。
81 * このため、アルファチャンネルの保持はオプションで指定するようにした方が良い。オプションが指定されなかった場合は背景に白マット(all(255,255,255))を適用してRGB画像にした後で変換を行う。
82
83
84 修理しないといけないところメモ
85--------------------------------
86
87 * 余計にRGB<->YUV変換してたり余計に拡大処理してたりするのをブラッシュアップする(issue #2)
88