Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Halideによる画像処理について
Search
saturday06
March 27, 2017
Programming
2.8k
2
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Halideによる画像処理について
saturday06
March 27, 2017
More Decks by saturday06
See All by saturday06
HLSの遅延を350ms+ネットワーク遅延分まで削減する
saturday06
3
2.4k
Other Decks in Programming
See All in Programming
PHP Application における Kubernetes 内 gRPC 通信
ganchiku
0
590
5分で問診!Composer セキュリティ健康診断
codmoninc
0
960
今さら聞けない .NET CLI
htkym
0
190
komatsuna「分散システムにおけるバグ分析手法」
komatsunaqa
0
250
S3 を使うアプリケーションをローカル完結で動かすことに全力を注いでみた / Running S3 Apps Offline
contour_gara
0
430
Claude CodeとAgentCore Gatewayを繋ぐ際の認証認可 / Authentication and authorization when connecting Claude Code with AgentCore Gateway
har1101
2
270
生成AI導入の「期待外れ」を乗り越える ー 開発フロー改革が目指す、真の組織変革
starfish719
0
4.3k
<title><a id="</title>君はこのHTMLをパースできるか"></a></title> #雑LT_study
pizzacat83
0
140
Detecting Compromised CI with eBPF and Cilium Tetragon
lizrice
0
170
the container ship “Apple Silicon”@WWDC26 Recap -Japan-\(region).swift
shingangan
0
120
Claude Code全社展開のためにやったことn選~プラグイン302個・コミッター271人を支えるために~
kenchan
5
1.5k
AWS DevOps AgentのAzure接続機能を検証して見えた活用法/Use Cases Verified for the AWS DevOps Agent's Azure Connectivity Feature
masakiokuda
1
230
Featured
See All Featured
Avoiding the “Bad Training, Faster” Trap in the Age of AI
tmiket
0
200
How to build an LLM SEO readiness audit: a practical framework
nmsamuel
1
850
Claude Code のすすめ
schroneko
67
230k
How GitHub (no longer) Works
holman
316
150k
How to Talk to Developers About Accessibility
jct
2
500
30 Presentation Tips
portentint
PRO
1
370
Navigating Team Friction
lara
192
16k
Sharpening the Axe: The Primacy of Toolmaking
bcantrill
46
2.9k
Lightning Talk: Beautiful Slides for Beginners
inesmontani
PRO
2
630
First, design no harm
axbom
PRO
2
1.2k
Music & Morning Musume
bryan
47
7.3k
The AI Revolution Will Not Be Monopolized: How open-source beats economies of scale, even for LLMs
inesmontani
PRO
3
3.7k
Transcript
Halideによる 画像処理について 2017/03/14 ピクシブ株式会社 茂木 勇
目次 - Halide概要 - Halideでぼかし処理 - Halideで画像縮小処理 - ベンチマーク
Halideとは? - C++の画像処理ライブラリ - 「ハロゲン化合物」という意味 - ライブラリではあるが「ハイパフォーマンスな画像処理を行うことができる新しい言 語」と名乗っている - 開発者「1500行のマルチスレッドとアセンブラで最適化されたPhotoshopのとある
フィルタのC++のコードを3ヶ月で10倍高速化した」 - http://halide-lang.org/assets/lectures/Halide_CVPR_intro.pdf
None
None
Halideの特徴 - C++の文法で数式を記述し、Halideが内部に持っているLLVMでコンパイルするこ とで画像処理用の関数を生成する - 数式自体をコンパイル、最適化をするので「縮小して輝度を上げる」など複数の画 像処理を組み合わせた際にパフォーマンスが向上する可能性がある - SSE,AVX,NEON等CPUのSIMD命令及びCUDA,OpenCLなどGPUを使った最適 化に対応している。
- CPU用に書いた処理をほとんど変更せず GPUでも動かせる
例: 近傍4ピクセルを使ったぼかし処理 blur(x, y) = (src(x-1,y) + src(x,y-1) + src(x,y)
+ src(x+1,y) + src(x,y+1))/5
例: 近傍4ピクセルを使ったぼかし処理(Halide版) Func src = …; Func blur; Var x,
y; blur(x, y) = (src(x-1,y)+src(x,y-1)+src(x,y)+src(x+1, y)+src(x,y+1))/5;
例: 近傍4ピクセルを使ったぼかし処理(Halide版) Func src = BoundaryConditions::repeat_edge(...); Func blur; Var x,
y; blur(x, y) = (src(x-1,y)+src(x,y-1)+src(x,y)+src(x+1, y)+src(x,y+1))/5; 画像端のデータを繰り返す
例: 近傍4ピクセルを使ったぼかし処理(Halide版) ImageParam input(type_of<uint8_t>(), 2); Func src = BoundaryConditions::repeat_edge(input); Func
blur; Var x, y; blur(x, y) = (src(x-1,y)+src(x,y-1)+src(x,y)+src(x+1, y)+src(x,y+1))/5; 入力画像データの定義
例: 近傍4ピクセルを使ったぼかし処理(Halide版) ImageParam input(type_of<uint8_t>(), 2); Func src = BoundaryConditions::repeat_edge(input); Func
blur; Var x, y; blur(x, y) = (src(x-1,y)+src(x,y-1)+src(x,y)+src(x+1, y)+src(x,y+1))/5; blur.compile_to_static_library("blur", {input}); これらを内部のLLVMで コンパイルして、 Cのライブラリとして出力
例: 近傍4ピクセルを使ったぼかし処理(Halide版) #include <Halide.h> int main() { using namespace Halide;
ImageParam input(type_of<uint8_t>(), 2); Func src = BoundaryConditions::repeat_edge(input); Func blur; Var x, y; blur(x, y) = (src(x-1,y)+src(x,y-1)+src(x,y)+src(x+1, y)+src(x,y+1))/5; blur.compile_to_static_library("blur", {input}); return 0; }
#include <Halide.h> int main() { using namespace Halide; ImageParam input(type_of<uint8_t>(),
2); Func src = BoundaryConditions::repeat_edge(input); Func blur; Var x, y; blur(x, y) = (src(x-1,y)+src(x,y-1)+src(x,y)+src(x+1, y)+src(x,y+1))/5; blur.compile_to_static_library("blur", {input}); return 0; } 例: 近傍4ピクセルを使ったぼかし処理(Halide版)
#include <Halide.h> int main() { using namespace Halide; ImageParam input(type_of<uint8_t>(),
2); Func src = BoundaryConditions::repeat_edge(input); Func blur; Var x, y; blur(x, y) = (src(x-1,y)+src(x,y-1)+src(x,y)+src(x+1, y)+src(x,y+1))/5; blur.compile_to_static_library("blur", {input}); return 0; } 例: 近傍4ピクセルを使ったぼかし処理(Halide版)
例: 近傍4ピクセルを使ったぼかし処理(Halide版) ImageParam input(type_of<uint8_t>(), 2); Func src = BoundaryConditions::repeat_edge(input); Func
blur; Var x, y; blur(x, y) = (src(x-1,y)+src(x,y-1)+src(x,y)+src(x+1, y)+src(x,y+1))/5;
例: 近傍4ピクセルを使ったぼかし処理(Halide版) ImageParam input(type_of<uint8_t>(), 2); Func src = BoundaryConditions::repeat_edge(input); Func
blur; Var x, y; blur(x, y) = (src(x-1,y)+src(x,y-1)+src(x,y)+src(x+1, y)+src(x,y+1))/5; 画素値は8bit整数のため 足し算結果がオーバーフローしている
例: 近傍4ピクセルを使ったぼかし処理(Halide版) ImageParam input(type_of<uint8_t>(), 2); Func src = BoundaryConditions::repeat_edge(input); Func
blur; Var x, y; blur(x, y) = src(x-1,y)/5+src(x,y-1)/5+src(x,y)/5+src(x+1, y)/5+src(x,y+1)/5; オーバーフローしにくいように修正 (型変換とかもできる)
#include <Halide.h> int main() { using namespace Halide; ImageParam input(type_of<uint8_t>(),
2); Func src = BoundaryConditions::repeat_edge(input); Func blur; Var x, y; blur(x, y) = src(x-1,y)/5+src(x,y-1)/5+src(x,y)/5+src(x+1, y)/5+src(x,y+1)/5; blur.compile_to_static_library("blur", {input}); return 0; } 例: 近傍4ピクセルを使ったぼかし処理(Halide版)
blur(x, y) = src(x-1,y)/5+src(x,y-1)/5+src(x,y)/5+src(x+1, y)/5+src(x,y+1)/5; blur.gpu_tile(x, y, 16, 16); auto
target = Halide::get_host_target(); target.set_feature(Target::OpenCL); blur.compile_to_static_library("blur", {input}, "", target); return 0; } 例: 近傍4ピクセルを使ったぼかし処理(Halide版) GPU使う場合
画像縮小処理 - pixivではサムネイル作成用の画像縮小にffmpeg(libswscale) を用いているが、幾つかの問題点があり乗り換え先を検討し ている - 高速で、高品質な縮小処理が求められている - halideが代わりとして使えないか?
例: Nearest Neighber法による画像縮小処理 縮小
例: Nearest Neighber法による画像縮小処理 out(out_x, out_y) = in(nearest_in_x(out_x),nearest_in_y(out_y)) in画像 out画像
例: Nearest Neighber法による画像縮小処理(Halide) out(out_x, out_y) = in(nearest_in_x(out_x),nearest_in_y(out_y))
例: Nearest Neighber法による画像縮小処理(Halide) Func out; Var out_x, out_y; out(out_x, out_y)
= in(nearest_in_x(out_x),nearest_in_y(out_y)) 出力変数、関数定義
例: Nearest Neighber法による画像縮小処理(Halide) ImageParam in(type_of<uint8_t>(), 2); Param<uint32_t> out_width, out_height; Func
out; Var out_x, out_y; out(out_x, out_y) = in(nearest_in_x(out_x),nearest_in_y(out_y)) 入力画像、出力サイズ 定義
例: Nearest Neighber法による画像縮小処理(Halide) ImageParam in(type_of<uint8_t>(), 2); Param<uint32_t> out_width, out_height; Func
nearest_in_x; Var x; nearest_in_x(x) = x * in.width() / out_width; Func out; Var out_x, out_y; out(out_x, out_y) = in(nearest_in_x(out_x),nearest_in_y(out_y)) 「最近傍のx座標を取得」関数定義
例: Nearest Neighber法による画像縮小処理(Halide) ImageParam in(type_of<uint8_t>(), 2); Param<uint32_t> out_width, out_height; Func
nearest_in_y; Var y; nearest_in_y(y) = y * in.height() / out_height; Func nearest_in_x; Var x; nearest_in_x(x) = x * in.width() / out_width; Func out; Var out_x, out_y; out(out_x, out_y) = in(nearest_in_x(out_x),nearest_in_y(out_y)) 「最近傍のy座標を取得」関数定義
例: Nearest Neighber法による画像縮小処理(Halide) #include <Halide.h> int main() { using namespace
Halide; ImageParam in(type_of<uint8_t>(), 2); Param<uint32_t> out_width, out_height; Func nearest_in_x; Var x; nearest_in_x(x) = (x * in.width() + out_width / 2) / out_width; Func nearest_in_y; Var y; nearest_in_y(y) = (y * in.height() + out_height / 2) / out_height; Func out; Var out_x, out_y; out(out_x, out_y) = BoundaryConditions::repeat_edge(in)(nearest_in_x(out_x), nearest_in_y(out_y)); out.compile_to_static_library("nearest_neighber", {in, out_width, out_height}); return 0; } 現実の問題に対するワークアラウンドとか追加
例: Nearest Neighber法による画像縮小処理(Halide) #include <Halide.h> int main() { using namespace
Halide; ImageParam in(type_of<uint8_t>(), 2); Param<uint32_t> out_width, out_height; Func nearest_in_x; Var x; nearest_in_x(x) = (x * in.width() + out_width / 2) / out_width; Func nearest_in_y; Var y; nearest_in_y(y) = (y * in.height() + out_height / 2) / out_height; Func out; Var out_x, out_y; out(out_x, out_y) = BoundaryConditions::repeat_edge(in)(nearest_in_x(out_x), nearest_in_y(out_y)); out.compile_to_static_library("nearest_neighber", {in, out_width, out_height}); return 0; } in画像
例: Nearest Neighber法による画像縮小処理(Halide) #include <Halide.h> int main() { using namespace
Halide; ImageParam in(type_of<uint8_t>(), 2); Param<uint32_t> out_width, out_height; Func nearest_in_x; Var x; nearest_in_x(x) = (x * in.width() + out_width / 2) / out_width; Func nearest_in_y; Var y; nearest_in_y(y) = (y * in.height() + out_height / 2) / out_height; Func out; Var out_x, out_y; out(out_x, out_y) = BoundaryConditions::repeat_edge(in)(nearest_in_x(out_x), nearest_in_y(out_y)); out.compile_to_static_library("nearest_neighber", {in, out_width, out_height}); return 0; } in画像 out画像
ベンチマーク 内容: サイズ1600x3200のグレースケール画像を320x480に様々な方式で縮小 環境: MacBook Pro (Retina, 15-inch, Mid 2015)
Processor Name: Intel Core i7 Processor Speed: 2.2 GHz Total Number of Cores: 4 Memory: 16 GB GPU: Intel Iris Pro 1536 MB
ベンチマーク結果(小さい値だとより良い) Benchmark Time CPU ------------------------------------------------------- HalideResizeNearestNeighber 2083577 ns 2081819 ns
HalideResizeBilinear 10228914 ns 10225705 ns HalideResizeGpuBilinear 947467 ns 736395 ns FfmpegResizeFastBilinear 1418483 ns 1416548 ns FfmpegResizeBilinear 6036412 ns 6033964 ns FfmpegResizeLanczos3 18074324 ns 18070590 ns
Halideの特徴(再掲) - C++の文法で数式を記述し、Halideが内部に持っているLLVMでコンパイルするこ とで画像処理用の関数を生成する - 数式自体をコンパイル、最適化をするので「縮小して輝度を上げる」など複数の画 像処理を組み合わせた際にパフォーマンスが向上する可能性がある - x86,arm等CPUのSIMD命令及びCUDA、OpenCLを使った最適化に対応してい る。
- CPU用に書いた処理をほとんど変更せず GPUでも動かせる
ベンチマーク2 内容: サイズ1600x3200のグレースケール画像をネガポジ変換をして から320x480にバイリニア法で縮小
ベンチマーク結果2(小さい値だとより良い) Benchmark Time CPU ----------------------------------------------------------- HalideResizeBilinear 10228914 ns 10225705 ns
HalideNegateResizeBilinear 10417060 ns 10413506 ns FfmpegResizeBilinear 6036412 ns 6033964 ns OpenCVNegateFfmpegResizeBilinear 9038528 ns 9036810 ns
ベンチマーク結果まとめ - FFmpegのような職人芸コードに比べて速度60%くらいのコードが生成される - GPUにオフロードすることで、CPUでは実現不可能な速度で処理ができる - GPUの職人芸にどのくらい及んでいるのかはまだ未検証 - 数式DSLを内部のLLVMでコンパイルするため、複数の画像処理を組み合わせた際 には職人芸コードの組み合わせよりも高速なコードが生成される可能性がある