SlideShare ist ein Scribd-Unternehmen logo
1 von 142
Downloaden Sie, um offline zu lesen
マルチコアを用いた
画像処理
名古屋工業大学
福嶋 慶繁
SSII2014 チュートリアル
1
資料中のコードはGithub上にアップロード
https://github.com/norishigefukushima/SSII2014
自己紹介
2
氏名 福嶋 慶繁
所属 名古屋工業大学
専門 3次元画像処理,画像符号化,並列化
コンピュテーショナルフォトグラフィ
e-mail fukushima ”at” nitech.ac.jp
twitter @fukushima1981
多視点データベース
SIMD画像処理プログラミング
3
今後の課題として,GPUによる
高速化があげられる.
こんなセンテンスを
書いたことはありませんか?
質問
そのアルゴリズム,本当にGPUで速くなりますか?
その手法,GPUで並列化できますか?
GPUは100倍速くなる魔法の言葉ではありません!
4
発表の目的
• なぜ並列化する必要があるのか
• 並列化プログラミングの理解
• 並列化プログラムを書けるように
• CPUでもここまで速くなるんだという啓蒙活動
5
6
24コア 100%
@Xeon X5690 3.47GHz
背景
なぜ並列化が必要なのか?
7
ムーアの法則
8
集積回路上のトランジスタ数は
「18か月(=1.5年)ごとに倍なる」
Intel 4004
Intel Core i7
3960X
Core i7は
初期CPU
35万個分
クロック数の上限
ACMQueue, CPU DB: Recording Microprocessor History:
https://queue.acm.org/detail.cfm?id=2181798
CPUのクロック周波数は
2000年ごろの3 GHzで
ほぼ頭打ち
9
集積化は続き,CPUはマルチコアへ
10
スパコンの計算性能
プログラマのフリーランチの終焉
マルチコアプログラミングが必須に
Sutter, Herb. "The free lunch is over: A fundamental turn
toward concurrency in software." Dr. Dobb’s Journal 30.3
(2005): 202-210.
Core i7
さらに...ダークシリコン
• フリーランチ時代 ~2005
• トランジスタ数はクロック数へ
• ホモジニアス・マルチコア時代 2005~20??
• トランジスタ数はコア数へ
• へテロジニアスコアへ
• 高いクロック数を持つコアと複数のコアを持つ低速なコアとの複合
11
理由:発熱,電力対策
• トランジスタは搭載可能だが電力が足りない
• 熱を抑制するために高クロック化が不可能
• 不要なチップの部分の電源をオフに→ダークシリコン
• ターボブーストの理由
GPU
12
GPUとCPUの計算速度
13
GPUは年率1.7倍に集積度が向上
CPUよりも圧倒的に高速
http://michaelgalloy.com/2013/06/11/cpu-vs-gpu-performance.html
J.Y. Chen “GPU Technology Trends and Future
Requirements,” Proc. International Electron
Devices Meeting, Dec. 2009.
スーパーコンピュータ 京
14スパコン:京 10,000,000 GFLOPS
スパコン性能ランキング1位@2011年11月
モバイル:ARM Cortex-A15 64 GFLOPS
CPU:Core i7 Haswell 224 GFLOPS
GPU:GeForce GTX TITAN 4,700 GFLOPS
Why CPU?
1. GPUがついてるとは限らない
2. 消費電力
3. CPUで計算するほうが,
速いアルゴリズムも存在
15
GPUがCPUより100倍速いという神話を暴く
CPU-GPU間でのスループットの評価
• Lee, Victor W., et al. "Debunking the 100X GPU vs. CPU myth: an
evaluation of throughput computing on CPU and GPU." ACM
SIGARCH Computer Architecture News. Vol. 38. No. 3. ACM, 2010.
16
インテルからの反論
論文の要約
100倍なんてことはない!
10倍程度だ!
並列化が非常に利くアルゴリズムはGPUがより速い時代
※ただし,驚くほど高速化されるわけでもない
※FLOPSに注目→現在10倍程度の差
17
CPUのGPU化?
Intel Xeon Phi
インテル® Xeon Phi™ コプロセッサーは,最大 61 個のコアと 244 ス
レッドで構成され、最大 1.2 TFLOPS の演算性能を発揮します.ハード
ウェア、ソフトウェア,ワークロード,パフォーマンス、効率性におけ
る多様な要件に対応するため,さまざまな製品が用意されています.
18
Intel Xeon Phi 7120X
61コアのプロセッサ
1.2 GHz
512bit SIMD命令
※Titanは4TFlops
並列化の知識
並列化のための基礎知識と画像処理への応用
• アムダールの法則
• 粒度とオーバーヘッド
• フリンの分類
• デザインパターン
• 画像処理の分類
19
並列化とは?
複数の演算処理を同時に行うことで,
スループットやレイテンシの
改善を行うこと
複数のコアで計算すれば
計算速度が数倍に
20
並列化の基本事項
1.アムダールの法則
2.オーバーヘッド
3.粒度
4.スループットとレイテンシ
5.フリンの分類
21
アムダールの法則(Amdahl's law)
𝑆 =
1
(1 − 𝑃) +
𝑃
𝑁
22
S:高速化率
P:並列化率
N:プロセッサ数
0
2
4
6
8
10
12
14
16
18
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
高速化率(倍)
プロセッサ数数
P=0.9
P=1.0
P=0.8
P=0.0
P=0.7
アムダールが示す限界
並列化
不可
並列
可能
並列化率 90%並列化率 10%
並列化率:並列化可能な部分
並列化
不可
たとえ無限個のコアで並列化しても
並列化不可の部分は高速化不可能
並列
化
不可
並列可能
並列
化
不可
オーバーヘッド
コアをたくさん使うほど
スレッドを多数生成するほど
オーバヘッドが生じる
1. 共有メモリのロック
2. データの分配(データのコピーは時間がかかる)
3. スレッドの生成,起動,同期
24
画像処理の並列性
画像処理は高い並列性を有する
•画素
•ブロック
•フレーム
•シーケンス
25
任意の細かさで並列処理可能
粒度の設定
粒度
画素単位
ブロック単位
フレーム単位
シーケンス単位
26
粒度が細かいほどよく分解される.
→バランスよく計算できるがオーバーヘッドが大き
い.
細粒度
(fine-grain)
画素
ブロック
フレーム
シーケンス 疎粒度
(coarse-grain)
粒度の選び方
• 粒度が細かい → 均等な負荷分散 オーバーヘッド大
• 粒度が荒い → 負荷分散が不平等 オーバーヘッド小
1. スループットかレイテンシどちらかが大事か?
2. 計算量のデータ依存性
3. 分解可能かどうか?
考慮すべきポイント
並列性能における最適化パラメータ
スループット:単位時間あたりにどれだけ出力できるか
• 最大の速度で出力し続けたい場合
• 映画で使うようなCGのレンダリング
• ビデオのエンコーディング(非リアルタイム)
• 実験データの生成
レイテンシ:出力するまで最大どれだけ待つか
• インタラクティブな操作がしたい場合
• ゲーム
• 画像補正・フォトショップ
• デバッグ
28
※スループットを出すように
並列化するほうが簡単
粒度の選択結果
Task
A
Task B Task C Task D
無駄が多すぎ
O
H
オーバーヘッド
Task
A
Task B
Task C
Task D 無駄
無駄
無駄
O
H
O
H
O
H
O
H
オーバーヘッド多すぎ
並列化
最適
A
O
H
B
O
H
B
O
H
C
O
H
C
O
H
C
O
H
C
O
H
D
O
H
A
O
H
B
O
H
B
O
H
C
O
H
C
O
H
C
O
H
C
O
H
D
O
H
A
O
H
B
O
H
B
O
H
C
O
H
C
O
H
C
O
H
C
O
H
D
O
H
A
O
H
B
O
H
B
O
H
C
O
H
C
O
H
C
O
H
C
O
H
D
O
H
A
O
H
B
O
H
C
O
H
C
O
H
A
O
H
B
O
H
C
O
H
C
O
H
B
O
H
C
O
H
C
O
H
D
O
H
B
O
H
C
O
H
C
O
H
D
O
H
粒度の選択結果
~パーティクルフィルタを例として~
30
Result of particle filter by using MIST @Nagoya Univ.
重い
軽い
ブロックで分割した場合 粒子で分割した場合
細かすぎ
粒子を何個か
まとめて処理する
のがベスト
本日のチュートリアル内容での分類
• グラフィカルモデル(中レイテンシ)
• 2次元画像ではなく,尤度の次元を加えた3次元ボクセル処理
• 並列化不可能な最適化アルゴリズムが多々
• 超解像処理(低レイテンシ)
• ブロック単位で並列化
• すべての処理が高く並列性
• 機械学習( レイテンシ無視,高スループット)
• 複数台のマシンで並列化
• マシン間でのデータ共有
31
画像処理の並列化の分解例
1. 画素単位(SIMD,GPU)
2. ブロック単位(マルチコア)
3. フロー単位(マルチコア)
4. フレーム単位(スクリプトやgnu parallel)
5. データセット単位(計算機に処理を分散,batファイル)
32
※本プレゼンのスコープ
フリンの分類
Single Instruction, Single Data stream (SISD)
Single Instruction, Multiple Data streams (SIMD)
Multiple Instruction, Single Data stream (MISD)
Multiple Instruction, Multiple Data streams (MIMD)
33
※GPUはMIMDだが,SIMD風に書くときに最大のパフォーマンスを発揮する演算機
NVIDIAは,SIMT (Single Instruction, Multiple Thread) と呼称
SISD
• シングル
コア
SIMD
• SSE・AVX
GPU
MISD
• FPGA,H/W†
MIMD
• マルチ
コア
命令の並行度とデータの並行度に基づく4つの分類
†厳密には多段に適応するため,MISDではないという専門家の意見も
フリンの分類(図解)
PU
命令
データ
PU
PU
PU
PU
データ
命令
CPU
CPU
CPU
命令
PU
データP
U
P
U
P
U
P
U
データ
命令
SISD:逐次プログラム SIMD:一度の命令で複数
のデータ処理
MISD:対象外 MIMD:マルチスレッド
プログラミング 31
画像処理の並列化プログラミング
どのように画像処理を並列化実行するのか?
•粒度の選択
•データを並列
•命令を並列
35
パターンを学ぶ
構造化並列プログラミング
原著
Structured Parallel Programming: Patterns for Efficient Computation
Michael McCool (著), James Reinders (著), Arch Robison (著)
翻訳
構造化並列プログラミング―効率良い計算を行うためのパターン
マイケル・マックール (著), 菅原 清文 (翻訳), エクセルソフト (翻訳)
並列化のデザインパターン
効率のよい並列プログラムの形とパターンを示した最も詳しい教科書
36
並列化プログラミングの並列パターン
37Structured Parallel Processing p.21
画像処理で使う代表的なパターン
データ並列
•Map(4章)
•Stencil(7章)
•Reduction(5章)
•Scan (5章)
プロセス並列
•Fork-join(8章)
•Pile-line(9章)
38
Map
39
基本形.
すべての要素を並列化し,要素ごと
に計算する.
各要素に依存関係無し.
Stencil
40
Mapの発展形.
要素をまず集約した後,Mapのよう
に並列化し,要素ごとに計算する.
集約後に各要素に依存関係無し.
Reduction
41
並列化しづらい形1
分割統治法により,サブ領域で計算
した後に,その計算結果を統合す
る.
各要素に依存関係有り.
Scan
42
並列化しづらい形2
Reductionの処理をさらに多段に接
続した処理.この形になると無理な
並列化が必要か考えるところ.
各要素に依存関係大有り.
Fork-join
43
基本形.
並列化はすべてFork-join.
タスクやフローを並列する基本形.
Pile-line
44
Fork-joinの発展形.
多段式のパイプライン
画像処理への分類の適用
• ポイントオペレータ (Map)
• 閾値処理,LUT,色変換,アルファブレンド
• エリアオペレータ (Map)
• 平滑化フィルタなどFIRフィルタ,モルフォロジ演算,
• 周波数変換 (Scan ?専門的な分解方法が存在)
• フーリエ,サイン・コサイン,ウェーブレット
• 探索 (reduction)
• 最大値,最小値,レジストレーション
• 応用(fork-join, pipe-line)
• セグメンテーション,ステレオ対応,オプティカルフロー,SIFT...
45
実装
各パターンの具体的な実装方法
• OpenMP
• SIMD
46
並列化の実装手段
• PCクラスタ
• MPI(Message Passing Interface)
• マルチコア並列化(MIMD)
• OpenMP, Intel TBB, Intel Clik++, Concurrency(MSVC), Grand Central
Dispatch(Mac), C=CSTRIPES
• SIMD
• (X86: MMX,SSE, AVX, 3DNow!), (ARM:NEON)
• GPU
• Cuda, OpenCL, OpenACC
47
OpenCV3.0 Roadmap
Proc. ICVS
高速な外部ライブラリ
による高速化
並列化ライブラリ等
による高速化
ベクトル演算(SIMD)に
よる高速化(CPU,GPU)
48
並列化の比較
工程数
自由度・速度
Open MP
Intel TBB
各種
ライブラリ
ネイティブ
スレッド
49
簡単 手順が複雑
速い
自由
遅い
不自由
SIMD
並列化
OpenMP
#pragma omp parallel for
50
加算 (Map)
51
void add(uchar* a, uchar* b, uchar* dest, int num)
{
for(int i=0;i<num;i++)
{
dest[i] = a[i] + b[i];
}
}
void add_omp (uchar* a, uchar* b, uchar* dest, int num)
{
#pragma omp parallel for
for(int i=0;i<num;i++)
{
dest[i] = a[i] + b[i];
}
}
#pragma omp parallel for
この一行を追加するだけでforループが並列化される
ポイントオペレータ(Map)
下記処理は加算の部分a[i]+b[i]を書き直すだけ
• 四則演算
• その他の算術演算 min, max, exp, log,ガンマ,sin, cos, tan...
• 閾値処理
• テーブルを使った変換
• 色変換,
• アルファブレンドによるクロスディゾルブ
52
画素の合計(Reduction)
53
float sum(float* src, int num)
{
float ret=0.0f;
for(int i=0;i<num;i++)
{
ret += src[i];
}
return ret;
}
float sum_omp (float* src, int num)
{
float ret=0.0f;
#pragma omp parallel for
for(int i=0;i<num;i++)
{
ret += src[i];
}
return ret;
}
すべての画素の総和を取る
単純に並列化してはいけない.
Thread0
ret+=10
(ret:110)
Thread1
ret+=20
(ret:120)
Thread2
ret+=15
(ret:115)
Thread3
ret+=30
(ret:130)
画素の合計
54
float sum_omp_true (float* src, int num)
{
float ret=0.0f;
#pragma omp parallel for reduction(+:ret)
for(int i=0;i<num;i++)
{
ret += src[i];
}
return ret;
}
reduction(+:ret)が追加
全ての計算終了時に各々のretを総和
グローバルな変数に非同期に演算を書ける場合
データの読み込み,書き込み時に同期が取れない場合
計算結果が保証されない.
グローバル
ret=100
ret=0
Thread0
ret+=10
(ret:10)
ret=0
Thread1
ret+=20
(ret:20)
ret=0
Thread2
ret+=15
(ret:15)
ret=0
Thread3
ret+=30
(ret:30)
グローバル
ret=100+75
フィルタ(Stencil)
55
void boxfilter(float* src, float* dest, int w, int h, int r)
{
float normalize = 1.0f/(float)((2*r+1)*(2*r+1));
for(int j=r;j<h-r;j++)//画像端を無視
{
for(int i=r;i<w-r;i++)
{
float sum = 0.0f;
for(int l=-r;l<=r;l++)
{
for(int k=-r;k<=r;k++)
{
sum+= src[w*(j+l) + i+l];
}
}
dest[w*j+i] = sum*normalize;
}
}
}
4重ループの平滑化フィルタ
いろいろな場所を並列化可能
フィルタ
56
void boxfilter_omp1(float* src, float* dest, int w, int h, int r)
{
float normalize = 1.0f/(float)((2*r+1)*(2*r+1));
#pragma omp parallel for
for(int j=r;j<h-r;j++)//画像端を無視
{
for(int i=r;i<w-r;i++)
{
float sum = 0.0f;
for(int l=-r;l<=r;l++)
{
for(int k=-r;k<=r;k++)
{
sum+= src[w*(j+l) + i+l];
}
}
dest[w*j+i] = sum*normalize;
}
}
}
行単位で並列化
フィルタ
57
void boxfilter_omp2(float* src, float* dest, int w, int h, int r)
{
floatnormalize = 1.0f/(float)((2*r+1)*(2*r+1));
for(int j=r;j<h-r;j++)//画像端を無視
{
#pragma omp parallel for
for(int i=r;i<w-r;i++)
{
float sum = 0.0f;
for(int l=-r;l<=r;l++)
{
for(int k=-r;k<=r;k++)
{
sum+= src[w*(j+l) + i+l];
}
}
dest[w*j+i] = sum*normalize;
}
}
}
列単位で並列化
フィルタ
58
void boxfilter_omp3(float* src, float* dest, int w, int h, int r)
{
floatnormalize = 1.0f/(float)((2*r+1)*(2*r+1));
for(int j=r;j<h-r;j++)
{
for(int i=r;i<w-r;i++)
{
float sum = 0.0f;
#pragma omp parallel for reduction(+:sum)
for(int l=-r;l<=r;l++)
{
for(int k=-r;k<=r;k++)
{
sum+= src[w*(j+l) + i+l];
}
}
dest[w*j+i] = sum*normalize;
}
}
}
カーネルの行
単位で並列化
フィルタ~並列位置での比較~
どこで並列化するのが一番速いのか?
• 基本的には,一番外側のループ→行単位での並列化
• 分割回数が多さ,リダクション演算など,
オーバーヘッドが大きいため
• 高速化のためには可能な限り最大の粒度を持ったほうがよい
59
IIRフィルタ(Scan)
60
void iirfilter(float* src, float* dest, int w, int h, float a)
{
float ia = 1.0f-a;
for(int j=1;j<h-1;j++)//画像端を無視
{
for(int i=1;i<w-1;i++)
{
dest[w*j+i]=a*src[w*j+i] + ia* dest[w*j+(i-1)];
}
}
}
左の出力と自身をブレンドする
IIRフィルタ
効率的に計算するにはScanの形
が推奨されているが...
IIRフィルタ
61
void iirfilter_omp1(float* src, float* dest, int w, int h, float a)
{
float ia = 1.0f-a;
for(int j=1;j<h-1;j++)//画像端を無視
{
#pragma omp parallel for scan ?
for(int i=1;i<w-1;i++)
{
dest[w*j+i]= a * src[w*j+i]
+ia * dest[w*j+(i-1)];
}
}
}
OpenMPにScanの実装はないため
自分で実装する必要がある→
IIRフィルタ(Scan→Map)
62
外側ループをMapの形にして処理
※コア数が少ないから出来ること
※GPUではScanの実装が必須
void iirfilter_omp2(float* src, float* dest, int w, int
h, float a)
{
float ia = 1.0f-a;
#pragma omp parallel for
for(int j=1;j<h-1;j++)//画像端を無視
{
for(int i=1;i<w-1;i++)
{
dest[w*j+i]=a * src[w*j+i]
+ ia * dest[w*j+(i-1)];
}
}
}
依存関係のない並列化
Thread 1
Thread 2
Thread 3
Thread 4
Fork-join
• いろいろなフィルタ出力を行う場合
• ガウシアンフィルタ
• ボックスフィルタ
• ソーベルフィルタ
をそれぞれ出力する場合
63
void forkjoin_ex(float* src, float* dest0, float* dest1, float*
dest2, int w, int h, int r)
{
Gaussianfilter(src,dest0,w,h,r);
Sobelfilter(src,dest1,w,h,r);
boxfilter(src,dest0,w,h,r);
}
void forkjoin_ex_omp(float* src, float* dest0, float*
dest1, float* dest2, int w, int h, int r)
{
#pragma omp parallel sections
{
#pragma omp section
{
Gaussianfilter(src,dest0,w,h,r);
}
#pragma omp section
{
Sobelfilter(src,dest1,w,h,r);
}
#pragma omp section
{
boxfilter(src,dest0,w,h,r);
}
}
}
Pile-line
• ステレオマッチング
• 画素単位のコスト計算
• コスト集約(フィルタリング)
• 最適化
• ポストフィルタ
• SIFT
• DoG
• ローカライズ
• オリエンテーション
• ディスプリプション
64
Thread 1
Thread 2
Thread 3
Thread 4
もっとも簡単な並列化は画像4つ集めて
Map処理.ただしレイテンシが大きい
Pile-line
65
Thread 1
Thread 2
Thread 3
Thread 4
レイテンシも考慮して,入力・出力する
ただし,OpenMPで作るのは難しい
OpenMP vs Intel TBB
• 計算速度: Intel TBB > OpenMP
• 対応パターン: Intel TBB >> OpenMP
• 実装しやすさ: Intel TBB << OpenMP
• 習得の速さ: Intel TBB < OpenMP
OpenMPは簡単,TBBはパフォーマンスが高い
66
OpenCVにおける
スレッド並列化
• Intel TBBの並列化を参考にしてさま
ざまなバックエンドで動作可能なよ
うに拡張
• Intel TBB, OpenMP, MS PPL, Grand
Central Dispatch(Mac), C=CSTRIPES
• ラムダ式でも代用可
67
class addInvorker : public cv::ParallelLoopBody
{
private:
Mat *im1,*im2, *dst;
public:
addInvorker(Mat& src1, Mat& src2, Mat& dest_)
: im1(&src1), im2(&src1), dst(&dest_){;}
virtual void operator()( const cv::Range &r ) const
{
const int width = im1->cols;
for(int j=r.start;j<r.end;j++)
{
float* s1 = im1->ptr<float>(j);
float* s2 = im2->ptr<float>(j);
float* d = dst->ptr<float>(j);
for(int i=0;i<width;i++)
{
d[i]= s1[i]+s2[i];
}
}
}
};
void addParallelOpenCV(Mat& src1, Mat& src2, Mat&
dest)
{
addInvorker body(src1,src2,dest);
cv::parallel_for_(Range(0, dest.rows), body);
}
クラスを
呼び出すだけ
SIMD (SSE, AVX)
__m128i ma = _mm_load_si128((const __m128i*)(a+i));
__m128i mb = _mm_load_si128((const __m128i*)(b+i));
ma = _mm_add_epi8(ma,mb);
_mm_store_si128((__m128i*)(dest+i), ma);
68
SSE, AVXによるSIMD演算
ひとつの命令で複数のデータを一度に処理可能
→まとめた分だけ処理速度向上
SSE(少し前のCPUは対応)
• char x16, short x8, int x4, float x4, double x2
AVX(最近のCPUが対応)
• char x32, short x16, int x8, float x8, double x4
intrinsic 命令を使えばアセンブラの記述も不要
メモリ上のデータをSIMD演算用レジスタにロードする必要性
69
SIMDレジスタを指す変数 __m128, __m256
128bit(SSE) や256bit(AVX)レジスタを自由に切って使用
• 整数
• __m128i, __m256i
char, short, int, long に明示的な区別はないので使用に注意が必要
• 単精度小数点
• __m128, __m256
4倍速,8倍速
• 倍精度小数点
• __m128d, __m256d
• 2倍速,4倍速
70
128bitレジスタのイメージ
71
SIMD演算
72
加算(MAP)
73
void add(uchar* a, uchar* b, uchar* dest, int num)
{
for(int i=0;i<num;i++)
{
dest[i] = a[i] + b[i];
}
}
元は,たった3行
加算(MAP) uchar
74
void add_sse_uchar(uchar* a, uchar* b, uchar* dest, int num)
{
for(int i=0;i<num;i+=16)
{
//メモリ上の配列A,Bを各をレジスタへロード
__m128i ma = _mm_load_si128((const __m128i*)(a+i));
__m128i mb = _mm_load_si128((const __m128i*)(b+i));
//A,Bが保持されたレジスタの内容を加算してmaのレジスタにコピー
ma = _mm_add_epi8(ma,mb);
//計算結果のレジスタ内容をメモリ(dest)にストア
_mm_store_si128((__m128i*)(dest+i), ma);
}
}
必要な関数を呼び出すだけ!
レジスタの管理も不要
GPUのように,メモリの
ロード・ストアが必要
(ただし,非常に高速)
16個づつ処理
→ループアンロール
たった5行?
メモリのアライメント
• _mm_load_si128, _mm_store_si128
実は,この関数はメモリの番地が16バイト境界にそろっていな
いとプログラムが落ちます.代わりに下記関数を使えば,そのよ
うな制約は発生しません.ただし少々実行速度が遅いです.
• _mm_loadu_si128, _mm_storeu_si128
75
アドレス
0番地 16番地 32番地 48番地 64番地
OSはある定数倍の区切りを先頭にしたメモリのコピーしか出来ない
ほしい場所
実際コピーした場所
ほしい場所
実際コピーした場所
メモリのアライメントのそろえ方
原始的な方法
1. メモリを多めに確保します.
2. 適切な境界まで先頭ポインタをずらして使います.
3. ずらしたポインタを戻して開放します.
76
現在の新しいVisual Studio中ではこうなってるので実はどっちを使っても大丈
夫.
#define _mm_free(a) _aligned_free(a)
#define _mm_malloc(a, b) _aligned_malloc(a, b)
ダメ絶対!
この関数を使ってください. bに揃ええたいバイト数を入れれば調整してくれます.
・Visual Studio: _aligned_malloc(a, b), _aligned_free(a)
・gcc: _mm_malloc(a, b) , _mm_free(a)
加算(MAP) float
77
関数のsi128がpsに変換しただけ!
4個づつ処理
→ループアンロール
void add_sse_float(float* a, float* b, float* dest, int num)
{
for(int i=0;i<num;i+=4)
{
//メモリ上の配列A,Bを各をレジスタへロード
__m128 ma = _mm_load_ps((a+i));
__m128 mb = _mm_load_ps((b+i));
//A,Bが保持されたレジスタの内容を加算してmaのレジスタにコピー
ma = _mm_add_ps(ma,mb);
//計算結果のレジスタ内容をメモリ(dest)にストア
_mm_store_ps((dest+i), ma);
}
}
加算(MAP) float - AVX
78
SSEに比べてさらに倍の速度
_mm128 → _mm256に変わっただけ
Xeon phiのAVX512を使えばそのさらに倍も可能
8個づつ処理
→ループアンロール
void add_avx_float(float* a, float* b, float* dest, int num)
{
for(int i=0;i<num;i+=8)
{
//メモリ上の配列A,Bを各をレジスタへロード
__m256 ma = _mm256_load_ps((a+i));
__m256 mb = _mm256_load_ps((b+i));
//A,Bが保持されたレジスタの内容を加算してmaのレジスタにコピー
ma = _mm256_add_ps(ma,mb);
//計算結果のレジスタ内容をメモリ(dest)にストア
_mm256_store_ps((dest+i), ma);
}
}
SIMD演算の関数例
add
• 加算
Sub
• 減算
Mul
• 乗算
Div
• 除算
Abs
• 絶対値
Avg
• 平均値
Dp
• 内積
Floor
• 切り捨て
Ceil
• 切り上げ
Addsub
• 交互に
加算,減算
Hadd
• 要素間加算
Hsub
• 要素間加算
Psadbw
• SAD計算
Cmp
• 比較演算
Sqr
• 平方根
キャスト ビット演算
Popcnt
• ビット数上げ
79
これらの演算は明示的に使うと通常の関数を使うよりも高速化
画素値の合計(Reduction)
80
float sum(float* src, int num)
{
float ret=0.0f;
for(int i=0;i<num;i++)
{
ret += src[i];
}
return ret;
}
float sum2(float* src, int num)
{
float ret0=0.0f;
float ret1=0.0f;
float ret2=0.0f;
float ret3=0.0f;
for(int i=0;i<num;i+=4)
{
ret0 += src[4*i+0];
ret1 += src[4*i+1];
ret2 += src[4*i+2];
ret3 += src[4*i+3];
}
return ret0+ret1+ret2+ret3;
}
画素値の合計(Reduction)
81
float sum_sse_float(float* src, int num)
{
__m128 tms = _mm_setzero_ps();
for(int i=0;i<num;i+=4)
{
__m128 ms = _mm_load_ps(src+i);
tms = _mm_add_ps(tms,ms);
}
float data[4];
_mm_storeu_ps(data,tms);
return (data[0]+data[1]+data[2]+data[3]);
}
4単位で合計計算し,最後に
その単位ごとに合計する.
(最後のreduction計算はhaddでも可)
フィルタ
(Stencil)
82
void boxfilter_sse(float* src, float* dest, int w, int h, int r)
{
for(int j=r;j<h-r;j++)//画像端を無視
{
floatnormalize = 1.0f/(float)((2*r+1)*(2*r+1));
__m128 mnormalize = _mm_set1_ps(normalize);
for(int i=r;i<w-r;i+=4)//4画素ごとに処理
{
__m128 msum = _mm_setzero_ps();
for(int l=-r;l<=r;l++)
{
for(int k=-r;k<=r;k++)
{
__m128 ms=_mm_loadu_ps(src+w*(j+l) + i+l);
msum = _mm_add_ps(msum,ms);
}
}
msum = _mm_mul_ps(msum,mnormalize);
_mm_storeu_ps(dest+w*j+i,msum);
}
}
}
列単位に並列化
カーネル単位に並列化はしない
・カーネルサイズがSIMD幅に依存する
・リダクション処理が必要
4画素づつ平均を一度に求めている.
OpenMPと
SIMDは
併用可能
83
void boxfilter_sse_omp(float* src, float* dest, int w, int h, int r)
{
#pragma omp parallel for
for(int j=r;j<h-r;j++)//画像端を無視
{
floatnormalize = 1.0f/(float)((2*r+1)*(2*r+1));
__m128 mnormalize = _mm_set1_ps(normalize);
for(int i=r;i<w-r;i+=4)
{
__m128 msum = _mm_setzero_ps();
for(int l=-r;l<=r;l++)
{
for(int k=-r;k<=r;k++)
{
__m128 ms=_mm_loadu_ps(src+w*(j+l)+i+l);
msum = _mm_add_ps(msum,ms);
}
}
msum = _mm_mul_ps(msum,mnormalize);
_mm_storeu_ps(dest+w*j+i,msum);
}
}
}
画像の行をOpenMPで並列化
画像の列の処理をSIMDで並列化
IIRフィルタ
(Scan→Map)
84
void iirfilter2(float* src, float* dest, int w, int h, float a)
{
float* srct = new float[w*h];
transpose(src,srct);
float ia = 1.0f-a;
for(int i=1;i<w-1;i++)
{
for(int j=1;j<h-1;j+=4)
{
srct[w*i+j+0]=a*src[w*i+j] + ia* srct[w*(i-1)+(j+0)];
srct[w*i+j+1]=a*src[w*i+j] + ia* srct[w*(i-1)+(j+1)];
srct[w*i+j+2]=a*src[w*i+j] + ia* srct[w*(i-1)+(j+2)];
srct[w*i+j+3]=a*src[w*i+j] + ia* srct[w*(i-1)+(j+3)];
}
}
transpose(srct,dest);
delete[] srct;
}
転置
IIRフィルタ(Scan)
85
IIRフィルタをScanの形で表現すると
並列化しないほうが速いほどのコスト
転置することでMapの形に変形する
void iirfilter_sse(float* src, float* dest, int w, int h, float a)
{
float* srct = new float[w*h];
transpose(src,srct);
float ia = 1.0f-a;
const __m128 ma = _mm_set1_ps(a);
const __m128 mia = _mm_set1_ps(ia);
for(int i=1;i<w-1;i++)
{
for(int j=1;j<h-1;j+=4)
{
__m128 ms0 = _mm_loadu_ps(&src[w*i+j]);
__m128 ms1 = _mm_loadu_ps(&src[w*(i-1)+j]);
ms0 = _mm_mul_ps(ms0,ma);
ms1 = _mm_mul_ps(ms1,mia);
ms0 = _mm_add_ps(ms0,ms1);
_mm_storeu_ps(&src[w*i+j],ms0);
}
}
transpose(srct,dest);
delete[] srct;
}
SIMDのデメリット
ひとつの命令で複数のデータを一度に処理可能
しかし,言い換えれば,
• 要素の移動が煩雑
処理単位が決まっており,複数の命令を発行して移動する必要がある
• 要素毎の命令が出来ない
複数回の計算結果をブレンドすることで実現可能なため非効率
• 要素間の命令の効率が悪い
hadd(要素間を足して出力)など,簡単な命令ならある
86
各要素を移動させる命令は
非常に制約のある操作が必要
• 要素ごとに値を代入したりコピーしたりする命令
メモリを経由するため,この操作は非常に重たい
• insert(代入), extract(コピー)
• 各要素をレジスタ内,レジスタ間で移動する命令
非常に速いが操作が複雑
• unpack,pack ,blend,shuffle
87
_mm_unpack
88
_mm_packs
89
逆順で出力を指定
前二つがb側
後ろ2つがa側
0 1 2 3 4 5 6 7
__m128 a
3 2 5 4
__m128 b
__m128 c
_MM_SHUFFLE(0,1,2,3)
__m128 c = _mm_shuffle_ps(a,b,_MM_SHUFFLE(0,1,2,3))
意味: bの0番目の要素を最後に,bの1番目の要素を後ろから2番目に,
aの2番目の要素を先頭から2番目に,bの3番目の要素を先頭にシャフル
_mm_shuffle
Mask (0011->3)
_mm_blend
91
逆順で出力を指定
前二つがb側
後ろ2つがa側
0 1 2 3 4 5 6 7
__m128 a
0 1 6 7
__m128 b
__m128 c
__m128 c = _mm_blend_ps(a,b,mask)
意味: bの0番目の要素を最後に,bの1番目の要素を後ろから2番目に,
aの2番目の要素を先頭から2番目に,bの3番目の要素を先頭にシャフル
SIMDプログラミングの肝
• 粒度が細かい計算向き
• OpenMPなどマルチコア並列化と併用可能
• 要素間の計算が必要ない形に変換する
• shuffle,blendなどでデータをそろえる
92
図解
93
0 1 2 3
4 5 6 7
__m128 a
__m128 b
ベクトル間の演算は得意
要素同士の演算は苦手
各要素を別々に処理するには,複数回の命令を実行して,
必要なところを残して他を捨てる必要
ベクトル間のデータの並べかえは大変
OpenMP 4.0
OpenMPがSIMDによるベクトル化に対応
• マルチスレッドだけ(今まで)
#pragma omp parallel for
• SIMDだけ(4.0から)
#pragma omp parallel simd
• SIMDとスレッド(4.0から)
#pragma omp parallel for simd
94
Visual Studioは今のところOpenMP2.0まで対応
Intel compilerかgccが対応
並列化の効果が少ない場合
• 並列化の効果が少ない場合
• IIRフィルタ
• (アトミック命令が必要)ヒス
トグラムの生成
• インテグラルイメージの作成
• 値を合計する
• 並列化が不能~難しい
• 動的計画法
• エントロピー符号化 など前状
態に強く依存する処理
• 繰り返しが多い処理
• PDE (partial differential
equations)
• ニュートン法
• Fork-joinが増える→オーバー
ヘッド増
• 疎行列の処理
• メモリが非連続→メモリ律速
• メモリが許すならGPUへ
• 密行列の処理は非常に向いてる
95
モバイル端末では?
• android
• OpenMP
• TBB
• ARM SIMD NEON
• iPhone
• NEON
• Grand Central Dispatch
• OpenMP ?
• Intel TBB ?
• GPGPU on Mobile Devices
• OpenCL
96
#include <arm_neon.h>
void add9 (uint8x16_t *vec_in)
{
/* set sixteen elements of vec_9 to 9 */
uint8x16_t vec_9 =vmovq_n_u8(9);
/* add 9 to 16 vector elements using a NEON instruction */
*vec_in =vaddq_u8(*vec_in, vec_9);
}
SIMD NEON
64bit幅(MMXと同じ),128bit幅 (SSEと同じ)
関数名が違うだけでほぼ文法は同じ
実は重要なメモリのIO
97
記憶域へのアクセス
L1
L2
メモリ
HDD
ネットワーク
98
メモリの読み書きは高速だと
思っていませんか?
実は下手な計算よりも重たいです.
計算 vs メモリアクセス
1. すべての画素をコピーする
2. すべての画素に1を加算する
3. すべての画素に10を乗算する
実はこの処理の計算速度は
ほとんど変わりません
99
ボトルネックはCPU?それともIO?
• CPU律速,メモリ律速
• データの込みこみ
• 計算
• データの書き込み
100
メモリのパフォーマンスは6年で2倍
Hennessy & Patterson, Computer
Architecture, Morgan Kaufmann,2006
画像処理の場合,かなりのケースでメモリのIOがボトルネック
SIMDによるベクトル化を行うと,4倍速8倍速以上とベクトル長以上に
コードが高速化するのはこのボトルネックを解消しているのが要因
GPU・CPUのメモリIO速度
101
メモリのIO 計算能力
SRAM vs DRAM
• SRAM (キャッシュ)
• 速い (L1 キャッシュ→1CPUサイクル)
• 小容量
• 高い
• DRAM(主記憶)
• 遅い( 100CPUサイクル)
• 大容量
• 安い
102
メモリアクセスの最適化
メモリアクセスで重要なポイント
• 局所性
• アライメント
• アクセス順序
例題:行列の転置
• キャッシュブロッキング
• キャッシュに収まるようにデータ構造をブロッキングすること
103
キャッシュブロッキング ~行列転置~
104
行メジャーな
レイアウトを仮定
メモリのロードは1要素づつではなく幅を
持って一度にキャッシュに格納される
一度キャッシュに入ったら
ロードの無駄(キャッシュ
ミス)を防ぐように処理す
るのが最善
例えば4画素づつ
メモリにロード
キャッシュブロッキング ~行列転置~
105
ブロック単位で転置
対角以外をスワップ
ソートによる行列転置
106
1 5 9 13
2 6 10 14
3 7 11 15
4 8 12 16
1 5 9 13 2 6 10 14 3 7 11 15 4 8 12 16
1 2 5 6 9 10 13 14 3 4 7 8 11 12 15 16
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
1 2 3 4
5 6 7 8
9 10 11 12
13 14 15 16
#define _MM_TRANSPOSE4_PS(row0, row1, row2, row3) {¥
__m128 tmp3, tmp2, tmp1, tmp0; ¥
¥
tmp0 = _mm_shuffle_ps((row0), (row1), 0x44); ¥
tmp2 = _mm_shuffle_ps((row0), (row1), 0xEE); ¥
tmp1 = _mm_shuffle_ps((row2), (row3), 0x44); ¥
tmp3 = _mm_shuffle_ps((row2), (row3), 0xEE); ¥
¥
(row0) = _mm_shuffle_ps(tmp0, tmp1, 0x88); ¥
(row1) = _mm_shuffle_ps(tmp0, tmp1, 0xDD); ¥
(row2) = _mm_shuffle_ps(tmp2, tmp3, 0x88); ¥
(row3) = _mm_shuffle_ps(tmp2, tmp3, 0xDD);} ¥
転置の実装例
107
void transpose_sse_omp
(float* src, float* dest, int w, int h)
{
const int ww = 2*w;
const int www = 3*w;
#pragma omp parallel for
for(int j=0;j<h;j+=4)
{
float* s = src+w*j;
for(int i=0;i<w;i+=4)
{
__m128 m0 = _mm_load_ps(s+i);
__m128 m1 = _mm_load_ps(s+w+i);
__m128 m2 = _mm_load_ps(s+ww+i);
__m128 m3 = _mm_load_ps(s+www+i);
_MM_TRANSPOSE4_PS(m0,m1,m2,m3);
_mm_store_ps(dest+h*i+j,m0);
_mm_store_ps(dest+h*(i+1)+j,m1);
_mm_store_ps(dest+h*(i+2)+j,m2);
_mm_store_ps(dest+h*(i+3)+j,m3);
}
}
}
void transpose
(float* src, float* dest, int w, int h)
{
//naive imprimentation
for(int j=0;j<h;j++)
{
for(int i=0;i<w;i++)
{
dest[h*i+j] = src[w*j+i];
}
}
}
プログラムの最適化時はメモリにも注意
• 普段注目されているもの
• 積和の回数
• 実は最も重要なポイント
• ロードストアの回数
• キャッシュミスの割合(プロファイリングツール)
108
これまでを踏まえて
本気でコードを
オプティマイゼーションしたら
どうなるのか?
109
バイラテラルフィルタ
を高速化
110
void bilateralFilterNaive(Mat& src, Mat& dest, int d, double sigma_color, double
sigma_space)
{
Mat srcd;src.convertTo(srcd,CV_64F);
Mat destd = Mat::zeros(src.size(),CV_64F);
const int r = d/2;
for(int j=0;j<src.rows;j++)
{
for(int i=0;i<src.cols;i++)
{
double sum = 0.0;
double coeff = 0.0;
const double cp = srcd.at<double>(j,i);
for(int l=-r;l<=r;l++)
{
for(int k=-r;k<=r;k++)
{
if(sqrt(l*l+k*k)<=r && i+k>=0 && i+k<src.cols && j+l>=0 &&
j+l<src.rows )
{
double c = -0.5*exp(((srcd.at<double>(j+l,i+k)-
cp)*(srcd.at<double>(j+l,i+k)-cp))/(sigma_color*sigma_color));
double s = -0.5*exp((l*l+k*k)/(sigma_space*sigma_space));
coeff+=c*s;
sum+=srcd.at<double>(j+l,i+k)*c*s;
}
}
}
destd.at<double>(j,i)=sum/coeff;
}
}
destd.convertTo(dest,src.type());
}
22.6秒
バイラテラルフィルタ
エッジ保持する平滑化フィルタ
※パラメータ:半径19画素
※学生が書いたコードです.
バイラテラルフィルタ
を高速化
111
class BilateralFilter_8u_InvokerSSE4 : public cv::ParallelLoopBody
{
public:
BilateralFilter_8u_InvokerSSE4(Mat& _dest, const Mat& _temp, int _radiusH, int _radiusV, int _maxk,
int* _space_ofs, float *_space_weight, float *_color_weight) :
temp(&_temp), dest(&_dest), radiusH(_radiusH), radiusV(_radiusV),
maxk(_maxk), space_ofs(_space_ofs), space_weight(_space_weight), color_weight(_color_weight)
{
}
virtual void operator() (const Range& range) const
{
int i, j, k;
int cn = dest->channels();
Size size = dest->size();
#if CV_SSE4_1
bool haveSSE4 = checkHardwareSupport(CV_CPU_SSE4_1);
#endif
if( cn == 1 )
{
uchar CV_DECL_ALIGNED(16) buf[16];
uchar* sptr = (uchar*)temp->ptr(range.start+radiusV) + 16 * (radiusH/16 + 1);
uchar* dptr = dest->ptr(range.start);
const int sstep = temp->cols;
const int dstep = dest->cols;
for(i = range.start; i != range.end; i++,dptr+=dstep,sptr+=sstep )
{
j=0;
#if CV_SSE4_1
if( haveSSE4 )
{
for(; j < size.width; j+=16)//16 pixel unit
{
int* ofs = &space_ofs[0];
float* spw = space_weight;
const uchar* sptrj = sptr+j;
const __m128i sval0 = _mm_load_si128((__m128i*)(sptrj));
__m128 wval1 = _mm_set1_ps(0.0f);
__m128 tval1 = _mm_set1_ps(0.0f);
__m128 wval2 = _mm_set1_ps(0.0f);
__m128 tval2 = _mm_set1_ps(0.0f);
__m128 wval3 = _mm_set1_ps(0.0f);
__m128 tval3 = _mm_set1_ps(0.0f);
__m128 wval4 = _mm_set1_ps(0.0f);
__m128 tval4 = _mm_set1_ps(0.0f);
const __m128i zero = _mm_setzero_si128();
for(k = 0; k < maxk; k ++, ofs++,spw++)
{
__m128i sref = _mm_loadu_si128((__m128i*)(sptrj+*ofs));
_mm_store_si128((__m128i*)buf,_mm_add_epi8(_mm_subs_epu8(sval0,sref),_mm_subs_epu8(sref,sval0)));
__m128i m1 = _mm_unpacklo_epi8(sref,zero);
__m128i m2 = _mm_unpackhi_epi16(m1,zero);
m1 = _mm_unpacklo_epi16(m1,zero);
const __m128 _sw = _mm_set1_ps(*spw);
__m128 _w = _mm_mul_ps(_sw,_mm_set_ps(color_weight[buf[3]],color_weight[buf[2]],color_weight[buf[1]],color_weight[buf[0]]));
__m128 _valF = _mm_cvtepi32_ps(m1);
_valF = _mm_mul_ps(_w, _valF);
tval1 = _mm_add_ps(tval1,_valF);
wval1 = _mm_add_ps(wval1,_w);
_w = _mm_mul_ps(_sw,_mm_set_ps(color_weight[buf[7]],color_weight[buf[6]],color_weight[buf[5]],color_weight[buf[4]]));
_valF =_mm_cvtepi32_ps(m2);
_valF = _mm_mul_ps(_w, _valF);
tval2 = _mm_add_ps(tval2,_valF);
wval2 = _mm_add_ps(wval2,_w);
m1 = _mm_unpackhi_epi8(sref,zero);
m2 = _mm_unpackhi_epi16(m1,zero);
m1 = _mm_unpacklo_epi16(m1,zero);
_w = _mm_mul_ps(_sw,_mm_set_ps(color_weight[buf[11]],color_weight[buf[10]],color_weight[buf[9]],color_weight[buf[8]]));
_valF =_mm_cvtepi32_ps(m1);
_valF = _mm_mul_ps(_w, _valF);
wval3 = _mm_add_ps(wval3,_w);
tval3 = _mm_add_ps(tval3,_valF);
_w = _mm_mul_ps(_sw,_mm_set_ps(color_weight[buf[15]],color_weight[buf[14]],color_weight[buf[13]],color_weight[buf[12]]));
_valF =_mm_cvtepi32_ps(m2);
_valF = _mm_mul_ps(_w, _valF);
wval4 = _mm_add_ps(wval4,_w);
tval4 = _mm_add_ps(tval4,_valF);
}
tval1 = _mm_div_ps(tval1,wval1);
tval2 = _mm_div_ps(tval2,wval2);
tval3 = _mm_div_ps(tval3,wval3);
tval4 = _mm_div_ps(tval4,wval4);
_mm_stream_si128((__m128i*)(dptr+j), _mm_packus_epi16(_mm_packs_epi32( _mm_cvtps_epi32(tval1), _mm_cvtps_epi32(tval2)) , _mm_packs_epi32( _mm_cvtps_epi32(tval3), _mm_cvtps_epi32(tval4))));
}
}
#endif
for(; j < size.width; j++)
{
const uchar val0 = sptr[0];
float sum=0.0f;
float wsum=0.0f;
for(k=0 ; k < maxk; k++ )
{
int val = sptr[j + space_ofs[k]];
float w = space_weight[k]*color_weight[std::abs(val - val0)];
sum += val*w;
wsum += w;
}
//overflow is not possible here => there is no need to use CV_CAST_8U
dptr[j] = (uchar)cvRound(sum/wsum);
}
}
}
else
{
short CV_DECL_ALIGNED(16) buf[16];
const int sstep = 3*temp->cols;
const int dstep = dest->cols*3;
uchar* sptrr = (uchar*)temp->ptr(3*radiusV+3*range.start ) + 16 * (radiusH/16 + 1);
uchar* sptrg = (uchar*)temp->ptr(3*radiusV+3*range.start+1) + 16 * (radiusH/16 + 1);
uchar* sptrb = (uchar*)temp->ptr(3*radiusV+3*range.start+2) + 16 * (radiusH/16 + 1);
uchar* dptr = dest->ptr(range.start);
for(i = range.start; i != range.end; i++,sptrr+=sstep,sptrg+=sstep,sptrb+=sstep,dptr+=dstep )
{
j=0;
#if CV_SSE4_1
if( haveSSE4 )
{
for(; j < size.width; j+=16)//16 pixel unit
{
int* ofs = &space_ofs[0];
float* spw = space_weight;
const uchar* sptrrj = sptrr+j;
680倍速
33.2ミリ秒
• 同じCPU
• 同じコンパイラオプション
• 精度そのまま,近時なし
研究紹介
112
MRF,CRFを並列化
無向グラフは高い並列性
確率伝播法など(BP,SGM,ICP)
• ボクセル空間でのフィルタ
• 画素(x,y)尤度(z)の次元処理
• 尤度を連続になるようにするとベクトル化しやすい
• Middleburyのライブラリなど離散的なものは特に
グラフ処理
• グラフカット
• Cuda Cut: グラフカットのGPU実装
• SIMDによるグラフ表現は少し難しい
• SIMDの拘束は,ノード間のグラフ定義の自由度を著しく低下させる
113
超解像を並列処理
超解像は基本的にはFIRフィルタの繰り返しで表現可能
• 全工程が並列処理可能
• デノイズ
• デブラー
• アップサンプル
• 位置あわせ
114
機械学習を並列処理
数万枚もの画像処理が必要→複数台の計算機で並列処理!
• Mahout https://mahout.apache.org/
• Hadoop上で動く機械学習ライブラリ
• Map Reduce
• スケーラビリティを最重視
• Jubatus http://jubat.us/ja/
• 日本発!!!!!
• データ分析に特化
• 複雑な処理も可能
• 低レイテンシ
115
エッジ保持平滑化フィルタ
116
• セグメンテーション
• スーパーピクセル
• ステレオ対応
• オプティカルフロー推定
• アルファマッティング
• トランジションマップ
• 顕著性マップ
• トーンマッピング
• etc…
バイラテラルフィルタ:エッジ保持しつつ,平滑化
• 用途はデノイジングだけではない!
• ラベリング問題全般に使用可能!!
アルゴリズムの実装と並列化
• グローバル最適化(MRF,CRF,凸最適化...)よりも
• フィルタ処理(bilateral filter, guided filter…)のほうが
圧倒的に高速く,並列性も高い
解くべき問題に必要とされる精度が,フィルタリ
ングで十分ならばフィルタリングを選択すべき
117
コンピュテーショナルフォトグラフィ
• エッジ保持平滑化フィルタ
• アルゴリズム的に高速
• イメージベーストレンダリング
• 3次元画像
• ノンフォトリアリスティックレン
ダリング
118
OpenCP: library for computational photography
https://github.com/norishigefukushima/OpenCP
Filters
• Fast Gaussian IIR filter
• *bilateral filter and its fast implementations or
variants: *separable filter *bilateral grid
*constant time O(1) bilateral filter *real-time O(1)
bilateral filter *joint bilateral filter *trilateral filter
*dual bilateral filter *weighted (joint) bilateral filter
epsilon filter
• cost volume filters, histogram filters:
*3D bilateral filter *3D guided filter *weighted mode filter
*constant time median filter *joint nearest filter
• Other edge preserving filters :
non-local means filter guided filter domain transform filter
recursive bilateral filter L0 Smoothing Weighted least
squre (WLS) smoothing Gaussian KD-Tree
permutohedral lattice adaptive manifold shiftable DXT
thresholding filter
Various applications
• De-noising
• De-blurirng
• up-sample/single image super resolution
• flash/non flash photography
• HDR
• colorization
• detail enhancement
• stylization, abstraction
• pencil sketch
• up-sample for pixel art, depth map
• removing coding noise
• blur regeneration
• Haze remove
• depth map estimation/refinement
• optical flow estimation/refinement
• alpha matting
119
Removing Depth Map Coding Distortion by
Using Post Filter Set
• デプスマップの符号化歪みをリアルタイム除去するアルゴリズム
• 10数ms以内にすべての処理を終了させるビデオプロセッシング
120
Proc. IEEE International Conference on Multimedia and Expo (ICME 2013), July 2013.
projectページ:
http://nma.web.nitech.ac.jp/fukushima/research/depthmap_postfilter.html
Weighted Joint Bilateral Filter with Slope Depth
Compensation Filter for Depth Map Refinement
121
Proc. International Conference on Computer Vision Theory and Applications (VISAPP 2013), Feb. 2013.
実時間でデプスマップの輪郭補正を行う手法
フィルタ処理をすべてTBB, SIMDで並列化
Kinect等のインプットがかなりきれいに
projectページ:
http://nma.web.nitech.ac.jp/fukushima/research/weightedj
ointbilateralfilter.html
Filter Based Alpha Matting for
Depth Image Based Rendering
• 左右の画像から任意視点の画像を合成
• 物体境界をアルファマッティングすることで高品質な画像合成
を実現
• マッティング処理を並列化
122
in Proc. IEEE Visual Communications and Image Processing (VCIP), Nov. 2013
projectページ:
http://nma.web.nitech.ac.jp/fukushima/research/viewsynth
esis.html
アルゴリズムの最適な選択
並列性,メモリ効率を考えると最適なアルゴリズムは通常と
は異なる
• クイックソートが最適とは限らない→バイトニックソート
• O(1)フィルタは小さいカーネルのときは重たい
インテグラルイメージ vs ナイーブな実装
O(1)メディアンフィルタ vs 3x3メディアンフィルタ
並列化を考えると,かなりの数のアルゴリズムが
ナイーブな実装がより実用的
123
まとめ
• CPU上での並列化プログラミング
• ムーアの法則,アムダールの法則,粒度,SIMD, MIMD
• デザインパターン: Map, Stencil, Reduction, Scan, Fork-join, Pile-line
• OpenMP, SIMD Intrinsics
• メモリIO
124
共同研究先募集中
「その処理,680倍高速化します!」
※当社比調べ
本日のコードはGithub上にアップロード
https://github.com/norishigefukushima/SSII2014
参考文献
125
The Art of Multiprocessor Programming
• OSに近い場所の話から始めて並列化の事例まで説明した教科書
126
The Art of Multiprocessor Programming 並行プログラミングの原理から実践まで [大型本]
Maurice Herlihy (著), Nir Shavit (著), 株式会社クイープ (翻訳)
コンピュータの構成と設計
• 計算機アーキテクチャから学習する
• 一般的な教科書:学部生の教科書
127
アセンブラ画像処理プログラミング
―SIMDによる処理の高速化
128
SIMDによる画像処理について書かれたほぼ唯一の本
すべてアセンブラなため入門者向けではない
基本的な事項を列挙
発展的な内容の記述は少ない
Slideshare
組み込み関数(intrinsic)によるSIMD入門
http://www.slideshare.net/FukushimaNorishige/simd-10548373
• intrinsicsを使ったSIMDプログラミング資料
• 日本語はこれだけ!?
129
Intelの日本語技術資料
• Webページ
• http://www.intel.co.jp/content/www/jp/ja/developer/download.html
• インテル® 64 アーキテクチャーおよび
IA-32 アーキテクチャー最適化リファレンス・マニュアル
(なんと788ページ)
• ソフトウェア開発者向けコード最適化マニュアル
130
OpenCV, Eigen, fftw, x264,ffmpeg
のソースコード
• SIMDや並列化の参考になるコードがたくさん
• OpenCV http://opencv.org/
• Eigen http://eigen.tuxfamily.org/index.php?title=Main_Page
• fftw http://www.fftw.org/
• x264 http://www.videolan.org/developers/x264.html
• ffmpeg http://www.ffmpeg.org/
• libjpeg-turbo http://libjpeg-turbo.virtualgl.org/
• WebP https://developers.google.com/speed/webp/?csw=1
131
その他の話題
132
高速化の手順
1. コンパイラを変える
2. 最適化が本当に必要か一歩立ち止まる
3. 最良なアルゴリズムの適用する
4. 演算数を減らす
1. 代入,LUTの使用
2. ループの外へ計算結果を
5. メモリアクセスをシーケンシャルにする
6. マルチコア並列化を行う
7. SIMD最適化を行う
133
1日で覚える簡単高速化
• コンパイラをiccに
• 最も速度に影響を与えるのはメモリの配置
• データはアクセスする連続に並べる
• メモリ使用量を減らす(テンポラリを極力減らす)
• マルチコアの利用~OpenMPによる並列化~
• ループの外側に #pragma omp parallel for
134
OpenMP遅いとおもったら?
• 同一メモリにアクセスしていませんか?
メモリアクセスの衝突が生じ,バスの取り合いが起こっている
可能性があります.共有メモリといってもキャッシュは各CPU
が持っているためその構造を生かして衝突を回避しましょう.
• Parallel 指示行でスレッド生成しています.このスレッド生成は
少ないほうがオーバーヘッドが少なくて済みます.
すべてのループに#pragma omp parallel forを記述するのではな
く
外側に並列化構造を作り#pragma omp forで済むか確認しま
しょう.
• Intel TBBを試してみましょう.
MPI (Message Passing Interface)について
• 複数の計算機のプロセッサをマルチコアとみなして計算する言
語,ライブラリ
• メモリの状態を共有するために,メッセージをやり取りし,メ
モリの状態の同期が必要(コスト大)
• 画像処理の場合,そこまでする( MPIまで使う)なら複数台の
マシンに別の画像を投げたほうがパフォーマンスが高い
136
アルゴリズムが並列化可能かの簡易テスト
• 順番どおりに動かないと計算結果がおかしくなる
• 逆順に動作させても動くかどうかを検証
137
用語:並行性 vs 並列性
• 並行性(コンカレンシー)とは
• 複数のタスクを同時に実行・処理する性質
• 並列性(パラレリズム)とは
• 並行性を活用して,問題を最短時間で解こうとすること
※いろいろ定義の流派がありますがこちらで解釈していま
す.
138
コンパイラの自動並列化はどこまで出来
るのか?
• 簡単な構造なら自動並列化してくれるが...
• gcc- O3 ...のような手軽さで高速化はまだまだ先
• Intel SPMD Program Compiler
• オープンソースのSIMD用コンパイラ
• http://ispc.github.io/
• BSDライセンス
139
高速化されたライブラリの情報
無料
• OpenCV
• 画像処理,行列演算,FFT,GPU関数も
• Eigen
行列演算
• fftw
• 無償最速 fftライブラリ
• ffte
• 最近のfftライブラリ.並列化した場合こちらのほうが速いときも
有料
• Intel® Integrated Performance Primitives (IPP)
• CPU最速 信号処理,画像処理
• Intel® Math Kernel Library (MKL)
• BLAS,LAPACK,FFTなど
140
Cuda vs OpenCL
• よほどコアな処理(nvidiaのカードに特化した処理など)をしない
限りCudaとOpenCLは処理速度は変わらない
• だたし,Cudaのほうが短く書くことが出来る
• OpenCLはCPU(マルチコア)向けにもコードを書くことが出来るた
め汎用性が高い
• ただしOpenCLでかかれたマルチコア用のコードはOpenMPで並列化するより
も遅い
• Cudaはnvidia専用言語しかしデファクトスタンダートに
• 汎用性を考えるとOpenCLが有利?
141
画像処理のSIMDベクトル化に関する論文
• R. Kutil, “Parallelization of IIR filters using SIMD
extensions,”Proc. IWSSIP, pp. 65-68, Bratislava, June 2008.
• Shahbahrami, A.; Juurlink, B.; Vassiliadis, S., "Performance
comparison of SIMD implementations of the discrete wavelet
transform," Application-Specific Systems, Architecture Processors,
2005. ASAP 2005. 16th IEEE International Conference on , vol.,
no., pp.393,398, 23-25 July 2005
142

Weitere ähnliche Inhalte

Was ist angesagt?

CPU / GPU高速化セミナー!性能モデルの理論と実践:実践編
CPU / GPU高速化セミナー!性能モデルの理論と実践:実践編CPU / GPU高速化セミナー!性能モデルの理論と実践:実践編
CPU / GPU高速化セミナー!性能モデルの理論と実践:実践編Fixstars Corporation
 
Swin Transformer (ICCV'21 Best Paper) を完璧に理解する資料
Swin Transformer (ICCV'21 Best Paper) を完璧に理解する資料Swin Transformer (ICCV'21 Best Paper) を完璧に理解する資料
Swin Transformer (ICCV'21 Best Paper) を完璧に理解する資料Yusuke Uchida
 
いまさら聞けないarmを使ったNEONの基礎と活用事例
いまさら聞けないarmを使ったNEONの基礎と活用事例いまさら聞けないarmを使ったNEONの基礎と活用事例
いまさら聞けないarmを使ったNEONの基礎と活用事例Fixstars Corporation
 
LLVMで遊ぶ(整数圧縮とか、x86向けの自動ベクトル化とか)
LLVMで遊ぶ(整数圧縮とか、x86向けの自動ベクトル化とか)LLVMで遊ぶ(整数圧縮とか、x86向けの自動ベクトル化とか)
LLVMで遊ぶ(整数圧縮とか、x86向けの自動ベクトル化とか)Takeshi Yamamuro
 
深層学習フレームワークにおけるIntel CPU/富岳向け最適化法
深層学習フレームワークにおけるIntel CPU/富岳向け最適化法深層学習フレームワークにおけるIntel CPU/富岳向け最適化法
深層学習フレームワークにおけるIntel CPU/富岳向け最適化法MITSUNARI Shigeo
 
分散深層学習 @ NIPS'17
分散深層学習 @ NIPS'17分散深層学習 @ NIPS'17
分散深層学習 @ NIPS'17Takuya Akiba
 
backbone としての timm 入門
backbone としての timm 入門backbone としての timm 入門
backbone としての timm 入門Takuji Tahara
 
いまさら聞けない!CUDA高速化入門
いまさら聞けない!CUDA高速化入門いまさら聞けない!CUDA高速化入門
いまさら聞けない!CUDA高速化入門Fixstars Corporation
 
モデル高速化百選
モデル高速化百選モデル高速化百選
モデル高速化百選Yusuke Uchida
 
【メタサーベイ】基盤モデル / Foundation Models
【メタサーベイ】基盤モデル / Foundation Models【メタサーベイ】基盤モデル / Foundation Models
【メタサーベイ】基盤モデル / Foundation Modelscvpaper. challenge
 
画像キャプションの自動生成
画像キャプションの自動生成画像キャプションの自動生成
画像キャプションの自動生成Yoshitaka Ushiku
 
【Unity】 Behavior TreeでAIを作る
 【Unity】 Behavior TreeでAIを作る 【Unity】 Behavior TreeでAIを作る
【Unity】 Behavior TreeでAIを作るtorisoup
 
条件分岐とcmovとmaxps
条件分岐とcmovとmaxps条件分岐とcmovとmaxps
条件分岐とcmovとmaxpsMITSUNARI Shigeo
 
Introduction to YOLO detection model
Introduction to YOLO detection modelIntroduction to YOLO detection model
Introduction to YOLO detection modelWEBFARMER. ltd.
 
画像処理ライブラリ OpenCV で 出来ること・出来ないこと
画像処理ライブラリ OpenCV で 出来ること・出来ないこと画像処理ライブラリ OpenCV で 出来ること・出来ないこと
画像処理ライブラリ OpenCV で 出来ること・出来ないことNorishige Fukushima
 
Automatic Mixed Precision の紹介
Automatic Mixed Precision の紹介Automatic Mixed Precision の紹介
Automatic Mixed Precision の紹介Kuninobu SaSaki
 
CUDAプログラミング入門
CUDAプログラミング入門CUDAプログラミング入門
CUDAプログラミング入門NVIDIA Japan
 
深層学習の数理:カーネル法, スパース推定との接点
深層学習の数理:カーネル法, スパース推定との接点深層学習の数理:カーネル法, スパース推定との接点
深層学習の数理:カーネル法, スパース推定との接点Taiji Suzuki
 

Was ist angesagt? (20)

CPU / GPU高速化セミナー!性能モデルの理論と実践:実践編
CPU / GPU高速化セミナー!性能モデルの理論と実践:実践編CPU / GPU高速化セミナー!性能モデルの理論と実践:実践編
CPU / GPU高速化セミナー!性能モデルの理論と実践:実践編
 
Swin Transformer (ICCV'21 Best Paper) を完璧に理解する資料
Swin Transformer (ICCV'21 Best Paper) を完璧に理解する資料Swin Transformer (ICCV'21 Best Paper) を完璧に理解する資料
Swin Transformer (ICCV'21 Best Paper) を完璧に理解する資料
 
いまさら聞けないarmを使ったNEONの基礎と活用事例
いまさら聞けないarmを使ったNEONの基礎と活用事例いまさら聞けないarmを使ったNEONの基礎と活用事例
いまさら聞けないarmを使ったNEONの基礎と活用事例
 
研究効率化Tips Ver.2
研究効率化Tips Ver.2研究効率化Tips Ver.2
研究効率化Tips Ver.2
 
LLVMで遊ぶ(整数圧縮とか、x86向けの自動ベクトル化とか)
LLVMで遊ぶ(整数圧縮とか、x86向けの自動ベクトル化とか)LLVMで遊ぶ(整数圧縮とか、x86向けの自動ベクトル化とか)
LLVMで遊ぶ(整数圧縮とか、x86向けの自動ベクトル化とか)
 
深層学習フレームワークにおけるIntel CPU/富岳向け最適化法
深層学習フレームワークにおけるIntel CPU/富岳向け最適化法深層学習フレームワークにおけるIntel CPU/富岳向け最適化法
深層学習フレームワークにおけるIntel CPU/富岳向け最適化法
 
分散深層学習 @ NIPS'17
分散深層学習 @ NIPS'17分散深層学習 @ NIPS'17
分散深層学習 @ NIPS'17
 
backbone としての timm 入門
backbone としての timm 入門backbone としての timm 入門
backbone としての timm 入門
 
いまさら聞けない!CUDA高速化入門
いまさら聞けない!CUDA高速化入門いまさら聞けない!CUDA高速化入門
いまさら聞けない!CUDA高速化入門
 
直交領域探索
直交領域探索直交領域探索
直交領域探索
 
モデル高速化百選
モデル高速化百選モデル高速化百選
モデル高速化百選
 
【メタサーベイ】基盤モデル / Foundation Models
【メタサーベイ】基盤モデル / Foundation Models【メタサーベイ】基盤モデル / Foundation Models
【メタサーベイ】基盤モデル / Foundation Models
 
画像キャプションの自動生成
画像キャプションの自動生成画像キャプションの自動生成
画像キャプションの自動生成
 
【Unity】 Behavior TreeでAIを作る
 【Unity】 Behavior TreeでAIを作る 【Unity】 Behavior TreeでAIを作る
【Unity】 Behavior TreeでAIを作る
 
条件分岐とcmovとmaxps
条件分岐とcmovとmaxps条件分岐とcmovとmaxps
条件分岐とcmovとmaxps
 
Introduction to YOLO detection model
Introduction to YOLO detection modelIntroduction to YOLO detection model
Introduction to YOLO detection model
 
画像処理ライブラリ OpenCV で 出来ること・出来ないこと
画像処理ライブラリ OpenCV で 出来ること・出来ないこと画像処理ライブラリ OpenCV で 出来ること・出来ないこと
画像処理ライブラリ OpenCV で 出来ること・出来ないこと
 
Automatic Mixed Precision の紹介
Automatic Mixed Precision の紹介Automatic Mixed Precision の紹介
Automatic Mixed Precision の紹介
 
CUDAプログラミング入門
CUDAプログラミング入門CUDAプログラミング入門
CUDAプログラミング入門
 
深層学習の数理:カーネル法, スパース推定との接点
深層学習の数理:カーネル法, スパース推定との接点深層学習の数理:カーネル法, スパース推定との接点
深層学習の数理:カーネル法, スパース推定との接点
 

Andere mochten auch

ガイデットフィルタとその周辺
ガイデットフィルタとその周辺ガイデットフィルタとその周辺
ガイデットフィルタとその周辺Norishige Fukushima
 
並列プログラミング 入門!&おさらい!
並列プログラミング入門!&おさらい!並列プログラミング入門!&おさらい!
並列プログラミング 入門!&おさらい!道化師 堂華
 
NumPyが物足りない人へのCython入門
NumPyが物足りない人へのCython入門NumPyが物足りない人へのCython入門
NumPyが物足りない人へのCython入門Shiqiao Du
 
できる!並列・並行プログラミング
できる!並列・並行プログラミングできる!並列・並行プログラミング
できる!並列・並行プログラミングPreferred Networks
 
【Unite 2017 Tokyo】C#ジョブシステムによるモバイルゲームのパフォーマンス向上テクニック
【Unite 2017 Tokyo】C#ジョブシステムによるモバイルゲームのパフォーマンス向上テクニック【Unite 2017 Tokyo】C#ジョブシステムによるモバイルゲームのパフォーマンス向上テクニック
【Unite 2017 Tokyo】C#ジョブシステムによるモバイルゲームのパフォーマンス向上テクニックUnity Technologies Japan K.K.
 
30分で博士号がとれる画像処理講座
30分で博士号がとれる画像処理講座30分で博士号がとれる画像処理講座
30分で博士号がとれる画像処理講座Sakiyama Kei
 

Andere mochten auch (6)

ガイデットフィルタとその周辺
ガイデットフィルタとその周辺ガイデットフィルタとその周辺
ガイデットフィルタとその周辺
 
並列プログラミング 入門!&おさらい!
並列プログラミング入門!&おさらい!並列プログラミング入門!&おさらい!
並列プログラミング 入門!&おさらい!
 
NumPyが物足りない人へのCython入門
NumPyが物足りない人へのCython入門NumPyが物足りない人へのCython入門
NumPyが物足りない人へのCython入門
 
できる!並列・並行プログラミング
できる!並列・並行プログラミングできる!並列・並行プログラミング
できる!並列・並行プログラミング
 
【Unite 2017 Tokyo】C#ジョブシステムによるモバイルゲームのパフォーマンス向上テクニック
【Unite 2017 Tokyo】C#ジョブシステムによるモバイルゲームのパフォーマンス向上テクニック【Unite 2017 Tokyo】C#ジョブシステムによるモバイルゲームのパフォーマンス向上テクニック
【Unite 2017 Tokyo】C#ジョブシステムによるモバイルゲームのパフォーマンス向上テクニック
 
30分で博士号がとれる画像処理講座
30分で博士号がとれる画像処理講座30分で博士号がとれる画像処理講座
30分で博士号がとれる画像処理講座
 

Ähnlich wie マルチコアを用いた画像処理

El text.tokuron a(2019).watanabe190613
El text.tokuron a(2019).watanabe190613El text.tokuron a(2019).watanabe190613
El text.tokuron a(2019).watanabe190613RCCSRENKEI
 
Can A Python Go Beyond The Python
Can A Python Go Beyond The PythonCan A Python Go Beyond The Python
Can A Python Go Beyond The PythonYusuke Muraoka
 
Introduction to Chainer (LL Ring Recursive)
Introduction to Chainer (LL Ring Recursive)Introduction to Chainer (LL Ring Recursive)
Introduction to Chainer (LL Ring Recursive)Kenta Oono
 
動的計画法の並列化
動的計画法の並列化動的計画法の並列化
動的計画法の並列化Proktmr
 
RubyのGC改善による私のエコライフ
RubyのGC改善による私のエコライフRubyのGC改善による私のエコライフ
RubyのGC改善による私のエコライフNarihiro Nakamura
 
C++コミュニティーの中心でC++をDISる
C++コミュニティーの中心でC++をDISるC++コミュニティーの中心でC++をDISる
C++コミュニティーの中心でC++をDISるHideyuki Tanaka
 
Python physicalcomputing
Python physicalcomputingPython physicalcomputing
Python physicalcomputingNoboru Irieda
 
Goコンパイラのきもち
GoコンパイラのきもちGoコンパイラのきもち
Goコンパイラのきもちmjhd-devlion
 
Rtミドルウェア講習会 第3部資料 配布版
Rtミドルウェア講習会 第3部資料 配布版Rtミドルウェア講習会 第3部資料 配布版
Rtミドルウェア講習会 第3部資料 配布版openrtm
 
【Unity道場スペシャル 2017札幌】乱数完全マスター
【Unity道場スペシャル 2017札幌】乱数完全マスター 【Unity道場スペシャル 2017札幌】乱数完全マスター
【Unity道場スペシャル 2017札幌】乱数完全マスター Unity Technologies Japan K.K.
 
コンピュータの整列処理で正解との距離は単調に減少するか?
コンピュータの整列処理で正解との距離は単調に減少するか?コンピュータの整列処理で正解との距離は単調に減少するか?
コンピュータの整列処理で正解との距離は単調に減少するか?yamahige
 
【Unity道場スペシャル 2017京都】乱数完全マスター 京都編
【Unity道場スペシャル 2017京都】乱数完全マスター 京都編【Unity道場スペシャル 2017京都】乱数完全マスター 京都編
【Unity道場スペシャル 2017京都】乱数完全マスター 京都編Unity Technologies Japan K.K.
 
センパイ!このプログラムクラッシュするんですけど。。。
センパイ!このプログラムクラッシュするんですけど。。。センパイ!このプログラムクラッシュするんですけど。。。
センパイ!このプログラムクラッシュするんですけど。。。yjono Seino
 
新しい並列for構文のご提案
新しい並列for構文のご提案新しい並列for構文のご提案
新しい並列for構文のご提案yohhoy
 
第3回 JavaScriptから始めるプログラミング2016
第3回 JavaScriptから始めるプログラミング2016第3回 JavaScriptから始めるプログラミング2016
第3回 JavaScriptから始めるプログラミング2016kyoto university
 
2011.7.3 札幌C++勉強会#2「C++のマクロはどこまで関数をいじれるのか」
2011.7.3 札幌C++勉強会#2「C++のマクロはどこまで関数をいじれるのか」2011.7.3 札幌C++勉強会#2「C++のマクロはどこまで関数をいじれるのか」
2011.7.3 札幌C++勉強会#2「C++のマクロはどこまで関数をいじれるのか」Hiro H.
 
もしも… Javaでヘテロジニアスコアが使えたら…
もしも… Javaでヘテロジニアスコアが使えたら…もしも… Javaでヘテロジニアスコアが使えたら…
もしも… Javaでヘテロジニアスコアが使えたら…Yasumasa Suenaga
 
オブジェクト指向できていますか?
オブジェクト指向できていますか?オブジェクト指向できていますか?
オブジェクト指向できていますか?Moriharu Ohzu
 

Ähnlich wie マルチコアを用いた画像処理 (20)

El text.tokuron a(2019).watanabe190613
El text.tokuron a(2019).watanabe190613El text.tokuron a(2019).watanabe190613
El text.tokuron a(2019).watanabe190613
 
Can A Python Go Beyond The Python
Can A Python Go Beyond The PythonCan A Python Go Beyond The Python
Can A Python Go Beyond The Python
 
Introduction to Chainer (LL Ring Recursive)
Introduction to Chainer (LL Ring Recursive)Introduction to Chainer (LL Ring Recursive)
Introduction to Chainer (LL Ring Recursive)
 
Hpc148
Hpc148Hpc148
Hpc148
 
動的計画法の並列化
動的計画法の並列化動的計画法の並列化
動的計画法の並列化
 
RubyのGC改善による私のエコライフ
RubyのGC改善による私のエコライフRubyのGC改善による私のエコライフ
RubyのGC改善による私のエコライフ
 
C++コミュニティーの中心でC++をDISる
C++コミュニティーの中心でC++をDISるC++コミュニティーの中心でC++をDISる
C++コミュニティーの中心でC++をDISる
 
Python physicalcomputing
Python physicalcomputingPython physicalcomputing
Python physicalcomputing
 
Goコンパイラのきもち
GoコンパイラのきもちGoコンパイラのきもち
Goコンパイラのきもち
 
Rtミドルウェア講習会 第3部資料 配布版
Rtミドルウェア講習会 第3部資料 配布版Rtミドルウェア講習会 第3部資料 配布版
Rtミドルウェア講習会 第3部資料 配布版
 
【Unity道場スペシャル 2017札幌】乱数完全マスター
【Unity道場スペシャル 2017札幌】乱数完全マスター 【Unity道場スペシャル 2017札幌】乱数完全マスター
【Unity道場スペシャル 2017札幌】乱数完全マスター
 
コンピュータの整列処理で正解との距離は単調に減少するか?
コンピュータの整列処理で正解との距離は単調に減少するか?コンピュータの整列処理で正解との距離は単調に減少するか?
コンピュータの整列処理で正解との距離は単調に減少するか?
 
【Unity道場スペシャル 2017京都】乱数完全マスター 京都編
【Unity道場スペシャル 2017京都】乱数完全マスター 京都編【Unity道場スペシャル 2017京都】乱数完全マスター 京都編
【Unity道場スペシャル 2017京都】乱数完全マスター 京都編
 
センパイ!このプログラムクラッシュするんですけど。。。
センパイ!このプログラムクラッシュするんですけど。。。センパイ!このプログラムクラッシュするんですけど。。。
センパイ!このプログラムクラッシュするんですけど。。。
 
新しい並列for構文のご提案
新しい並列for構文のご提案新しい並列for構文のご提案
新しい並列for構文のご提案
 
第3回 JavaScriptから始めるプログラミング2016
第3回 JavaScriptから始めるプログラミング2016第3回 JavaScriptから始めるプログラミング2016
第3回 JavaScriptから始めるプログラミング2016
 
Gurobi python
Gurobi pythonGurobi python
Gurobi python
 
2011.7.3 札幌C++勉強会#2「C++のマクロはどこまで関数をいじれるのか」
2011.7.3 札幌C++勉強会#2「C++のマクロはどこまで関数をいじれるのか」2011.7.3 札幌C++勉強会#2「C++のマクロはどこまで関数をいじれるのか」
2011.7.3 札幌C++勉強会#2「C++のマクロはどこまで関数をいじれるのか」
 
もしも… Javaでヘテロジニアスコアが使えたら…
もしも… Javaでヘテロジニアスコアが使えたら…もしも… Javaでヘテロジニアスコアが使えたら…
もしも… Javaでヘテロジニアスコアが使えたら…
 
オブジェクト指向できていますか?
オブジェクト指向できていますか?オブジェクト指向できていますか?
オブジェクト指向できていますか?
 

Mehr von Norishige Fukushima

計算スケジューリングの効果~もし,Halideがなかったら?~
計算スケジューリングの効果~もし,Halideがなかったら?~計算スケジューリングの効果~もし,Halideがなかったら?~
計算スケジューリングの効果~もし,Halideがなかったら?~Norishige Fukushima
 
多チャンネルバイラテラルフィルタの高速化
多チャンネルバイラテラルフィルタの高速化多チャンネルバイラテラルフィルタの高速化
多チャンネルバイラテラルフィルタの高速化Norishige Fukushima
 
3次元計測とフィルタリング
3次元計測とフィルタリング3次元計測とフィルタリング
3次元計測とフィルタリングNorishige Fukushima
 
デプスセンサとその応用
デプスセンサとその応用デプスセンサとその応用
デプスセンサとその応用Norishige Fukushima
 
複数台のKinectV2の使い方
複数台のKinectV2の使い方複数台のKinectV2の使い方
複数台のKinectV2の使い方Norishige Fukushima
 
Comparison between Blur Transfer and Blur Re-Generation in Depth Image Based ...
Comparison between Blur Transfer and Blur Re-Generation in Depth Image Based ...Comparison between Blur Transfer and Blur Re-Generation in Depth Image Based ...
Comparison between Blur Transfer and Blur Re-Generation in Depth Image Based ...Norishige Fukushima
 
Non-essentiality of Correlation between Image and Depth Map in Free Viewpoin...
Non-essentiality of Correlation between Image and Depth Map in Free Viewpoin...Non-essentiality of Correlation between Image and Depth Map in Free Viewpoin...
Non-essentiality of Correlation between Image and Depth Map in Free Viewpoin...Norishige Fukushima
 
コンピュテーショナルフォトグラフティの基礎
コンピュテーショナルフォトグラフティの基礎コンピュテーショナルフォトグラフティの基礎
コンピュテーショナルフォトグラフティの基礎Norishige Fukushima
 
Popcntによるハミング距離計算
Popcntによるハミング距離計算Popcntによるハミング距離計算
Popcntによるハミング距離計算Norishige Fukushima
 
コンピューテーショナルフォトグラフィ
コンピューテーショナルフォトグラフィコンピューテーショナルフォトグラフィ
コンピューテーショナルフォトグラフィNorishige Fukushima
 
OpenCVの拡張ユーティリティ関数群
OpenCVの拡張ユーティリティ関数群OpenCVの拡張ユーティリティ関数群
OpenCVの拡張ユーティリティ関数群Norishige Fukushima
 

Mehr von Norishige Fukushima (13)

計算スケジューリングの効果~もし,Halideがなかったら?~
計算スケジューリングの効果~もし,Halideがなかったら?~計算スケジューリングの効果~もし,Halideがなかったら?~
計算スケジューリングの効果~もし,Halideがなかったら?~
 
多チャンネルバイラテラルフィルタの高速化
多チャンネルバイラテラルフィルタの高速化多チャンネルバイラテラルフィルタの高速化
多チャンネルバイラテラルフィルタの高速化
 
3次元計測とフィルタリング
3次元計測とフィルタリング3次元計測とフィルタリング
3次元計測とフィルタリング
 
デプスセンサとその応用
デプスセンサとその応用デプスセンサとその応用
デプスセンサとその応用
 
複数台のKinectV2の使い方
複数台のKinectV2の使い方複数台のKinectV2の使い方
複数台のKinectV2の使い方
 
Libjpeg turboの使い方
Libjpeg turboの使い方Libjpeg turboの使い方
Libjpeg turboの使い方
 
Comparison between Blur Transfer and Blur Re-Generation in Depth Image Based ...
Comparison between Blur Transfer and Blur Re-Generation in Depth Image Based ...Comparison between Blur Transfer and Blur Re-Generation in Depth Image Based ...
Comparison between Blur Transfer and Blur Re-Generation in Depth Image Based ...
 
Non-essentiality of Correlation between Image and Depth Map in Free Viewpoin...
Non-essentiality of Correlation between Image and Depth Map in Free Viewpoin...Non-essentiality of Correlation between Image and Depth Map in Free Viewpoin...
Non-essentiality of Correlation between Image and Depth Map in Free Viewpoin...
 
コンピュテーショナルフォトグラフティの基礎
コンピュテーショナルフォトグラフティの基礎コンピュテーショナルフォトグラフティの基礎
コンピュテーショナルフォトグラフティの基礎
 
Popcntによるハミング距離計算
Popcntによるハミング距離計算Popcntによるハミング距離計算
Popcntによるハミング距離計算
 
コンピューテーショナルフォトグラフィ
コンピューテーショナルフォトグラフィコンピューテーショナルフォトグラフィ
コンピューテーショナルフォトグラフィ
 
OpenCVの拡張ユーティリティ関数群
OpenCVの拡張ユーティリティ関数群OpenCVの拡張ユーティリティ関数群
OpenCVの拡張ユーティリティ関数群
 
WebP入門
WebP入門WebP入門
WebP入門
 

Kürzlich hochgeladen

新人研修のまとめ 2024/04/12の勉強会で発表されたものです。
新人研修のまとめ       2024/04/12の勉強会で発表されたものです。新人研修のまとめ       2024/04/12の勉強会で発表されたものです。
新人研修のまとめ 2024/04/12の勉強会で発表されたものです。iPride Co., Ltd.
 
PHP-Conference-Odawara-2024-04-000000000
PHP-Conference-Odawara-2024-04-000000000PHP-Conference-Odawara-2024-04-000000000
PHP-Conference-Odawara-2024-04-000000000Shota Ito
 
[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略
[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略
[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略Ryo Sasaki
 
Amazon SES を勉強してみる その12024/04/12の勉強会で発表されたものです。
Amazon SES を勉強してみる その12024/04/12の勉強会で発表されたものです。Amazon SES を勉強してみる その12024/04/12の勉強会で発表されたものです。
Amazon SES を勉強してみる その12024/04/12の勉強会で発表されたものです。iPride Co., Ltd.
 
スマートフォンを用いた新生児あやし動作の教示システム
スマートフォンを用いた新生児あやし動作の教示システムスマートフォンを用いた新生児あやし動作の教示システム
スマートフォンを用いた新生児あやし動作の教示システムsugiuralab
 
20240412_HCCJP での Windows Server 2025 Active Directory
20240412_HCCJP での Windows Server 2025 Active Directory20240412_HCCJP での Windows Server 2025 Active Directory
20240412_HCCJP での Windows Server 2025 Active Directoryosamut
 
IoT in the era of generative AI, Thanks IoT ALGYAN.pptx
IoT in the era of generative AI, Thanks IoT ALGYAN.pptxIoT in the era of generative AI, Thanks IoT ALGYAN.pptx
IoT in the era of generative AI, Thanks IoT ALGYAN.pptxAtomu Hidaka
 
Postman LT Fukuoka_Quick Prototype_By Daniel
Postman LT Fukuoka_Quick Prototype_By DanielPostman LT Fukuoka_Quick Prototype_By Daniel
Postman LT Fukuoka_Quick Prototype_By Danieldanielhu54
 
UPWARD_share_company_information_20240415.pdf
UPWARD_share_company_information_20240415.pdfUPWARD_share_company_information_20240415.pdf
UPWARD_share_company_information_20240415.pdffurutsuka
 

Kürzlich hochgeladen (9)

新人研修のまとめ 2024/04/12の勉強会で発表されたものです。
新人研修のまとめ       2024/04/12の勉強会で発表されたものです。新人研修のまとめ       2024/04/12の勉強会で発表されたものです。
新人研修のまとめ 2024/04/12の勉強会で発表されたものです。
 
PHP-Conference-Odawara-2024-04-000000000
PHP-Conference-Odawara-2024-04-000000000PHP-Conference-Odawara-2024-04-000000000
PHP-Conference-Odawara-2024-04-000000000
 
[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略
[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略
[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略
 
Amazon SES を勉強してみる その12024/04/12の勉強会で発表されたものです。
Amazon SES を勉強してみる その12024/04/12の勉強会で発表されたものです。Amazon SES を勉強してみる その12024/04/12の勉強会で発表されたものです。
Amazon SES を勉強してみる その12024/04/12の勉強会で発表されたものです。
 
スマートフォンを用いた新生児あやし動作の教示システム
スマートフォンを用いた新生児あやし動作の教示システムスマートフォンを用いた新生児あやし動作の教示システム
スマートフォンを用いた新生児あやし動作の教示システム
 
20240412_HCCJP での Windows Server 2025 Active Directory
20240412_HCCJP での Windows Server 2025 Active Directory20240412_HCCJP での Windows Server 2025 Active Directory
20240412_HCCJP での Windows Server 2025 Active Directory
 
IoT in the era of generative AI, Thanks IoT ALGYAN.pptx
IoT in the era of generative AI, Thanks IoT ALGYAN.pptxIoT in the era of generative AI, Thanks IoT ALGYAN.pptx
IoT in the era of generative AI, Thanks IoT ALGYAN.pptx
 
Postman LT Fukuoka_Quick Prototype_By Daniel
Postman LT Fukuoka_Quick Prototype_By DanielPostman LT Fukuoka_Quick Prototype_By Daniel
Postman LT Fukuoka_Quick Prototype_By Daniel
 
UPWARD_share_company_information_20240415.pdf
UPWARD_share_company_information_20240415.pdfUPWARD_share_company_information_20240415.pdf
UPWARD_share_company_information_20240415.pdf
 

マルチコアを用いた画像処理