...

FixstarsiSTEP講演資料 (PDF/2.92MB)

by user

on
Category: Documents
6

views

Report

Comments

Transcript

FixstarsiSTEP講演資料 (PDF/2.92MB)
インテル® ソフトウェア・カンファレンス 2012
Optimization of lucille™ with
Intel® Parallel Studio XE 2013
2012.12.7
M3事業推進室 シニアディレクター
古坂 大地
©2012 Fixstars Corporation, All rights reserved.
アジェンダ
会社紹介
最適化事例紹介
 ターゲット・アプリの解説
 オリジナルプログラムのプロファイル
 コンパイル・オプションの設定
 SSE命令によるベクトル化
 AVX命令によるベクトル化
©2012 Fixstars Corporation, All rights reserved.
2
インテル® ソフトウェア・カンファレンス 2012
会社紹介
©2012 Fixstars Corporation, All rights reserved.
フィックスターズについて
フィックスターズは、マルチコアプロセッサにおけるトータルソ
リューションカンパニーです。
設立
2002年8月
社員数
87名(2012/11月 現在)
所在地
東京、カリフォルニア、ビクトリア
創業者
代表取締役会長 - 長谷川 智彦
Sunnyvale, CA
代表取締役社長 CEO - 三木 聡
Osaki, Tokyo
Victoria, BC
経営戦略顧問 - マイケル A. クスマノ
©2012 Fixstars Corporation, All rights reserved.
4
フィックスターズの事業
マルチコアプロセッサを活用し、お客様のビジネスを加速する
ためのサービスや製品を提供しています。
ソフトウェア製品
ソフトウェア開発サービス
Linux OS サポート
マルチコアシステム
©2012 Fixstars Corporation, All rights reserved.
技術サポート
お客様
5
注力分野
高速計算や大容量データ処理など、高いコンピューティングパ
ワーを必要とする分野にフォーカスしています。
Financial
Simulation
Computer
Graphics
Medical Imaging
Computer Vision
 プライシング・分析
 自動車設計
 CTスキャン
 外観検査
 リスク計量
 建築設計
 超音波診断装置
 マシンビジョン
 マーケット情報管理
 CGレンダリング
 MRI / PET
 動き探索
Simulation
©2012 Fixstars Corporation, All rights reserved.
Image processing
6
インテル® ソフトウェア・カンファレンス 2012
本日のメイン
©2012 Fixstars Corporation, All rights reserved.
対象アプリケーション
lucille™ | Global Illumination Renderer
 http://www.fixstars.com/lucille
 http://vimeo.com/fixstars
特徴
 レイトレース法を用いた3次元CGレンダラー
 間接光の影響も考慮した大域照明効果
 マルチコア・プロセッサ向け高速演算ライブラリ搭載
題材
 アンビエント・オクルージョン処理の高速化
©2012 Fixstars Corporation, All rights reserved.
8
M3 (エム・キューブ) プラットフォームとは?
“M3 (エム・キューブ)”は、
 マルチ・コア (Multi-Core)
 マルチ・ノード (Multi-Node)
 マルチ・アーキテクチャ(Multi-Architecture)
環境のためのソフトウェア開発/実行プラットフォーム。
主な特長
1. 並列コンピューティング環境における
ソフトウェア開発が容易
2. ハードウェアの持つ性能を最大限に
生かすライブラリ群
3. 複数の異なるアーキテクチャの CPU
をサポート
©2012 Fixstars Corporation, All rights reserved.
9
レンダリング環境
CPU
 Intel® Core™ i7-3770 3.4GHz (4 Cores)
RAM
 16 GB
ポリゴン総数
 約1,400万ポリゴン
出力解像度
 512 x 512
サブピクセルサンプリング
 1 x 1 (なし)
アンビエント・オクルージョン
サンプリング
 θ : 16 x Φ : 16 (= 256 rays)
©2012 Fixstars Corporation, All rights reserved.
10
アンビエント・オクルージョン (AO) とは
環境光による陰影をリアルに仕上げるCG効果
 オブジェクト間の隙間が少ないと、光が遮蔽されるので暗い。
 遮蔽度合いから環境光の寄与を計算し陰影をつける。
 明るい部分=遮蔽されていない。
ボディ上部
 フロントガラス

 暗い部分=遮蔽されている。


車体の下
ホイールの内部
©2012 Fixstars Corporation, All rights reserved.
11
レイトレース・レンダリングの並列化
タイル・レンダリングによるマルチスレッド化
 出力イメージを小さな矩形に領域分割し、タイルと
いう単位でレンダリング・ジョブとしてスケジュー
リング。
 タイルは、16ピクセル x 16ピクセル
タイル
©2012 Fixstars Corporation, All rights reserved.
12
ステップ1. プロファイリング
インテル® VTune™ Amplifier XEを用いてホットスポット解析。
ホットスポット上位のモジュールをチェック。
全体51.7%
 bbox4_test関数
空間データ構造(ツリー)のトラバース処理で用いられるBBOX判定処理。
 triangle_intersects関数 (aligned_triangle_intersectsd64関数)
トライアングル・プリミティブと光線の交差判定処理。
©2012 Fixstars Corporation, All rights reserved.
13
インテル® VTune™ Amplifier ホットスポット解析 (1)
©2012 Fixstars Corporation, All rights reserved.
14
インテル® VTune™ Amplifier ホットスポット解析 (2)
©2012 Fixstars Corporation, All rights reserved.
15
インテル® VTune™ Amplifier ホットスポット解析 (3)
©2012 Fixstars Corporation, All rights reserved.
16
AOの計算アルゴリズム
遮蔽度の計算
 物体表面から半球状にレイを放射し
て、他の物体表面との交点交差判定。
 今回は半球面上を256点サンプリング
θ方向→16分割、Φ方向→16分割。
 交差点の数とサンプリング点の比率。
 今回はスクリーン内の全サブピクセ
ルがAOの演算対象。
 膨大な交差判定計算が行われている。
512×512×256= 67,108,864回
©2012 Fixstars Corporation, All rights reserved.
17
交差判定計算
細分化された三角形と光線とが交差するかを幾何学的に求める。
t 
( s  e1 )  e2 
1
b  
 (d  e )  s 
2
v0
 1  (d  e )  e 

2
1
b2 
 ( s  e1 )  d 
共通項を代入計算。
s1  d  e2 , s2  s  e1
t 
 s2  e2 
b   1  s  s 
 1 s e  1 
b2  1 1  s2  d 
s
e1 t・d
e2
(b1, b2)
o
v1
v2
三角形の重心座標系から判定する。
1 if t  0 and b1  0 and b2  0 and b1  b2  1
hit  
otherwise
0
©2012 Fixstars Corporation, All rights reserved.
18
交差判定ソースコード (簡易版)
int triangle_intersects(...)
{
for (i = 0; i < ntriangles; i++) {
triangle& t = triangles[i];
vec3
vec3
vec3
vec3
e1
e2
d
s
=
=
=
=
if (t >= 0.0 &&
b1 >= 0.0 &&
b2 >= 0.0 &&
(b1 + b2) <= 1.0f &&
t < *dist)
{
*hit = 1;
*dist = t;
*u = b1;
*v = b2;
*find_index = i;
}
t.v1 – t.v0;
t.v2 – t.v0;
ray.dir;
ray.origin – t.v0;
vec3 s1 = cross(d, e2);
vec3 s2 = cross(s, e1);
double
double
double
double
div
t
b1
b2
=
=
=
=
dot(s1,
dot(s2,
dot(s1,
dot(s2,
©2012 Fixstars Corporation, All rights reserved.
e1);
e2) / div;
s) / div;
d) / div;
}
return SUCCESS;
}
19
交差判定オリジナルソースコード Part 1
int aligned_triangle_intersectsd64(
const float* triangles,
const size_t ntriangles,
const float* ray_origin,
const float* ray_dir,
float* dist,
float* u,
float* v,
size_t* find_index,
int*
hit)
{
*hit = 0;
for (size_t i = 0; i < ntriangles; i++) {
const float* v0 = &triangles[i*9+0];
const float* v1 = &triangles[i*9+3];
const float* v2 = &triangles[i*9+6];
©2012 Fixstars Corporation, All rights reserved.
20
交差判定オリジナルソースコード Part 2
int aligned_triangle_intersectsd64(...)
{
for (size_t i = 0; i < ntriangles; i++) {
... 前ページからの続き ...
double e1[3], e2[3], d[3], s[3];
for (int j = 0; j < 3; j++) {
e1[j] = v1[j] – v0[j];
e2[j] = v2[j] – v0[j];
d[j] = ray_dir[j];
s[j] = ray_origin[j] – v0[j];
}
t 
 s2  e2 
b   1  s  s 
 1 s e  1 
b2  1 1  s2  d 
double s1[3];
s1[0] = (d[1] * e2[2]) – (d[2] * e2[1]);
s1[1] = (d[2] * e2[0]) – (d[0] * e2[2]);
s1[2] = (d[0] * e2[1]) – (d[1] * e2[0]);
©2012 Fixstars Corporation, All rights reserved.
21
交差判定オリジナルソースコード Part 3
int aligned_triangle_intersectsd64(...)
{
for (size_t i = 0; i < ntriangles; i++) {
... 前ページからの続き ...
double s2[3];
s2[0] = (s[1] * e1[2]) – (s[2] * e1[1]);
s2[1] = (s[2] * e1[0]) – (s[0] * e1[2]);
s2[2] = (s[0] * e1[1]) – (s[1] * e1[0]);
t 
 s2  e2 
b   1  s  s 
 1 s e  1 
b2  1 1  s2  d 
double div;
div = (s1[0] * e1[0]) + (s1[1] * e1[1]) + (s1[2] * e1[2]);
double t, b1, b2;
t = ((s2[0] * e2[0]) + (s2[1] * e2[1]) + (s2[2] * e2[2])) / div;
b1 = ((s1[0] * s[0]) + (s1[1] * s[1]) + (s1[2] * s[2])) / div;
b2 = ((s2[0] * d[0]) + (s2[1] * d[1]) + (s2[2] * d[2])) / div;
©2012 Fixstars Corporation, All rights reserved.
22
交差判定オリジナルソースコード Part 4
int aligned_triangle_intersectsd64(...)
{
for (size_t i = 0; i < ntriangles; i++) {
... 前ページからの続き ...
if ((t >= 0.0) && (b1 >= 0.0) && (b2 >= 0.0) && (b1 + b2 <= 1.0) &&
(t < *dist)) {
*dist = t;
*u = b1;
*v = b2;
*find_index = i;
*hit = 1;
}
}
1 if t  0 and b1  0 and b2  0 and b1  b2  1
hit  
otherwise
0
return kReturnCodeSuccess;
}
©2012 Fixstars Corporation, All rights reserved.
23
ステップ2. インテル® C++ コンパイラー導入
標準コンパイラからインテル® C++ コンパイラーにスイッチ。
ホットスポット上位のモジュールをチェック。
ICCへスイッチする
だけで性能改善。
 bbox4_test関数
112.421秒 → 68.717秒
 triangle_intersects関数 (aligned_triangle_intersectsd64関数)
102.791秒 → 90.458秒
©2012 Fixstars Corporation, All rights reserved.
24
コンパイル・オプションの設定 (ICC導入前)
©2012 Fixstars Corporation, All rights reserved.
25
インテル® C++ コンパイラーへのスイッチ
©2012 Fixstars Corporation, All rights reserved.
26
コンパイル・オプションの設定 (1) 最適化
©2012 Fixstars Corporation, All rights reserved.
27
コンパイル・オプションの設定 (2) 最適化 (ICC)
©2012 Fixstars Corporation, All rights reserved.
28
コンパイル・オプションの設定 (3) コード生成 (ICC)
©2012 Fixstars Corporation, All rights reserved.
29
インテル® ソフトウェア・カンファレンス 2012
ハンド・オプティマイズ
©2012 Fixstars Corporation, All rights reserved.
インテル® Vtune™ Amplifier ラインプロファイル
©2012 Fixstars Corporation, All rights reserved.
31
交差判定オリジナルソースコード Part 1
int aligned_triangle_intersectsd64(
const float* triangles,
const size_t ntriangles,
const float* ray_origin,
const float* ray_dir,
float* dist,
float* u,
float* v,
size_t* find_index,
int*
hit)
{
*hit = 0;
for (size_t i = 0; i < ntriangles; i++) {
const float* v0 = &triangles[i*9+0];
const float* v1 = &triangles[i*9+3];
const float* v2 = &triangles[i*9+6];
©2012 Fixstars Corporation, All rights reserved.
最適化ポイント (1)
三角形頂点データのレイア
ウト構造の変更。
32
交差判定オリジナルソースコード Part 2
int aligned_triangle_intersectsd64(...)
{
for (size_t i = 0; i < ntriangles; i++) {
... 前ページからの続き ...
double e1[3], e2[3], d[3], s[3];
for (int j = 0; j < 3; j++) {
e1[j] = v1[j] – v0[j];
e2[j] = v2[j] – v0[j];
d[j] = ray_dir[j];
s[j] = ray_origin[j] – v0[j];
}
double s1[3];
s1[0] = (d[1] * e2[2]) – (d[2] * e2[1]);
s1[1] = (d[2] * e2[0]) – (d[0] * e2[2]);
s1[2] = (d[0] * e2[1]) – (d[1] * e2[0]);
©2012 Fixstars Corporation, All rights reserved.
最適化ポイント (2)
入 力 は FLOAT だ が 演 算 は
DOUBLEなので、要工夫。
最適化ポイント (3)
ループ不変式のループ外へ
の移動。
最適化ポイント (4)
外積計算(演算部)のベク
トル化。
33
交差判定オリジナルソースコード Part 3
int aligned_triangle_intersectsd64(...)
{
for (size_t i = 0; i < ntriangles; i++) {
... 前ページからの続き ...
double s2[3];
s2[0] = (s[1] * e1[2]) – (s[2] * e1[1]);
s2[1] = (s[2] * e1[0]) – (s[0] * e1[2]);
s2[2] = (s[0] * e1[1]) – (s[1] * e1[0]);
最適化ポイント (4)
外積計算のベクトル化。
最適化ポイント (5)
内積計算のベクトル化。
最適化ポイント (6)
除算式の除去 (乗算化)。
double div;
div = (s1[0] * e1[0]) + (s1[1] * e1[1]) + (s1[2] * e1[2]);
double t, b1, b2;
t = ((s2[0] * e2[0]) + (s2[1] * e2[1]) + (s2[2] * e2[2])) / div;
b1 = ((s1[0] * s[0]) + (s1[1] * s[1]) + (s1[2] * s[2])) / div;
b2 = ((s2[0] * d[0]) + (s2[1] * d[1]) + (s2[2] * d[2])) / div;
©2012 Fixstars Corporation, All rights reserved.
34
交差判定オリジナルソースコード Part 4
int aligned_triangle_intersectsd64(...)
{
for (size_t i = 0; i < ntriangles; i++) {
... 前ページからの続き ...
最適化ポイント (7)
条件分岐の除去もしくは削減。
if ((t >= 0.0) && (b1 >= 0.0) && (b2 >= 0.0) && (b1 + b2 <= 1.0) &&
(t < *dist)) {
*dist = t;
*u = b1;
最適化ポイント (8)
*v = b2;
*find_index = i;
ループ内依存変数の除去。
*hit = 1;
}
}
return kReturnCodeSuccess;
}
©2012 Fixstars Corporation, All rights reserved.
35
交差判定スカラ修正ソースコード Part 1
int aligned_triangle_intersectsd64(
const float* triangles,
const size_t ntriangles,
const float* ray_origin,
const float* ray_dir,
float* dist,
float* u,
float* v,
size_t* find_index,
int*
hit)
{
*hit = 0;
double o[3], d[3];
for (int i = 0; i < 3; i++) {
o[i] = ray_origin[i];
d[i] = ray_dir[i];
}
©2012 Fixstars Corporation, All rights reserved.
36
交差判定スカラ修正ソースコード Part 2
int aligned_triangle_intersectsd64(...)
{
for (size_t i = 0; i < ntriangles; i++) {
... 前ページからの続き ...
double e1[3], e2[3], s[3];
for (int j = 0; j < 3; j++) {
e1[j] = v1[j] – v0[j];
e2[j] = v2[j] – v0[j];
s[j] = o[j] – v0[j];
}
double s1[3];
s1[0] = (d[1] * e2[2]) – (d[2] * e2[1]);
s1[1] = (d[2] * e2[0]) – (d[0] * e2[2]);
s1[2] = (d[0] * e2[1]) – (d[1] * e2[0]);
©2012 Fixstars Corporation, All rights reserved.
37
交差判定スカラ修正ソースコード Part 3
int aligned_triangle_intersectsd64(...)
{
for (size_t i = 0; i < ntriangles; i++) {
... 前ページからの続き ...
double s2[3];
s2[0] = (s[1] * e1[2]) – (s[2] * e1[1]);
s2[1] = (s[2] * e1[0]) – (s[0] * e1[2]);
s2[2] = (s[0] * e1[1]) – (s[1] * e1[0]);
double inv;
inv = 1.0 / ((s1[0] * e1[0]) + (s1[1] * e1[1]) + (s1[2] * e1[2]));
double t, b1, b2;
t = ((s2[0] * e2[0]) + (s2[1] * e2[1]) + (s2[2] * e2[2])) * inv;
b1 = ((s1[0] * s[0]) + (s1[1] * s[1]) + (s1[2] * s[2])) * inv;
b2 = ((s2[0] * d[0]) + (s2[1] * d[1]) + (s2[2] * d[2])) * inv;
©2012 Fixstars Corporation, All rights reserved.
38
交差判定スカラ修正ソースコード Part 4
int aligned_triangle_intersectsd64(...)
{
for (size_t i = 0; i < ntriangles; i++) {
... 前ページからの続き ...
double check = MIN(t, MIN(b1, b2));
if ((check >= 0.0) && (b1 + b2 <= 1.0) && (t < *dist)) {
*dist = t;
*u = b1;
*v = b2;
*find_index = i;
*hit = 1;
}
}
return kReturnCodeSuccess;
}
©2012 Fixstars Corporation, All rights reserved.
39
ステップ3. スカラコード修正
ループ不変式の移動、除算除去、条件分岐削減などを整備する
除算式の除去が
最も効果あり。
 triangle_intersects関数 (aligned_triangle_intersectsd64関数)
90.458秒 → 75.233秒
©2012 Fixstars Corporation, All rights reserved.
40
ステップ4. データ構造の変更
現状の三角形頂点リストのデータ構造
 i番目のトライアングルTi
頂点v0 (x0, y0, z0)
 頂点v1 (x1, y1, z1)
 頂点v2 (x2, y2, z2)

x0
y0
z0
x1
y1
z1
x2
y2
z2
 このようなデータ構造ではベクタデータとして頂点データを効率よくレジ
スタにロードできない。
©2012 Fixstars Corporation, All rights reserved.
41
ステップ4. データ構造の変更 (続き)
ベクトル演算しやすいようにベクタ長のデータを効率よくロード
したい。
 例) エッジベクトル e1 の演算をベクトル化
 SSE命令であれば、
128ビットレジスタに対して4FLOATを一度にロードしベクトル演算。
for (int j = 0; j
e1[j] = v1[j]
e2[j] = v2[j]
s[j] = o[j]
}
©2012 Fixstars Corporation, All rights reserved.
<
–
–
–
3; j++) {
v0[j];
v0[j];
v0[j];
e1
=
v1
-
v0
e1
=
v1
-
v0
e1
=
v1
-
v0
e1
=
v1
-
v0
42
ステップ4. データ構造の変更 (続き)
オリジナルはトライアングルの0、1、・・・、Nの順番に
T0
x0
y0
z0
x1
y1
z1
x2
y2
z2
T1
x0
y0
z0
x1
y1
z1
x2
y2
z2
T2
x0
y0
z0
x1
y1
z1
x2
y2
z2
T3
x0
y0
z0
x1
y1
z1
x2
y2
z2
Ti
:
:
:
:
:
:
:
:
:
TN-3
x0
y0
z0
x1
y1
z1
x2
y2
z2
TN-2
x0
y0
z0
x1
y1
z1
x2
y2
z2
TN-1
x0
y0
z0
x1
y1
z1
x2
y2
z2
TN
x0
y0
z0
x1
y1
z1
x2
y2
z2
©2012 Fixstars Corporation, All rights reserved.
Array-Of-Structure
struct _triangle
{
struct _vertex
{
float x;
float y;
float z;
} vertices[3];
} triangles[N];
43
ステップ4. データ構造の変更 (続き)
ベクトル演算しやすいよう頂点座標x0、y0、z0・・・の順番に
T0
x0
y0
z0
x1
y1
z1
x2
y2
z2
Structure-Of-Array
T1
x0
y0
z0
x1
y1
z1
x2
y2
z2
T2
x0
y0
z0
x1
y1
z1
x2
y2
z2
T3
x0
y0
z0
x1
y1
z1
x2
y2
z2
Ti
:
:
:
:
:
:
:
:
:
struct _triangles
{
struct _vertices
{
float x[N];
float y[N];
float z[N];
} vertices[3];
} triangles;
TN-3
x0
y0
z0
x1
y1
z1
x2
y2
z2
TN-2
x0
y0
z0
x1
y1
z1
x2
y2
z2
TN-1
x0
y0
z0
x1
y1
z1
x2
y2
z2
TN
x0
y0
z0
x1
y1
z1
x2
y2
z2
©2012 Fixstars Corporation, All rights reserved.
頂点リストの先頭アドレスの
メモリ・アラインメントを揃え
るためにパディングを追加。
44
ステップ5. SSEによるオプティマイズ
入力データは単精度浮動小数ですが、演算部は倍精度演算を用い
ます。
単精度と倍精度では、ベクタレジスタのスロット数 (単精度4と倍
精度2) が異なるので、少し工夫が必要。
FLOAT
FLOAT
DOUBLE
FLOAT
FLOAT
DOUBLE
ロードは4FLOAT、演算はLOWの2FLOATとHIGHの2FLOATの2回
に分けて、DOUBLEにキャストして演算します。
FLOAT
FLOAT
DOUBLE
©2012 Fixstars Corporation, All rights reserved.
FLOAT
DOUBLE
DOUBLE
FLOAT
DOUBLE
45
Intrinsic関数によるSSE命令への書換え
外積計算
double s2[3];
s2[0] = (s[1] * e1[2]) – (s[2] * e1[1]);
s2[1] = (s[2] * e1[0]) – (s[0] * e1[2]);
s2[2] = (s[0] * e1[1]) – (s[1] * e1[0]);
__m128d
s2[0] =
s2[1] =
s2[2] =
s2[3];
_mm_sub_pd(_mm_mul_pd(s[1], e1[2]), _mm_mul_pd(s[2], e1[1]));
_mm_sub_pd(_mm_mul_pd(s[2], e1[0]), _mm_mul_pd(s[0], e1[2]));
_mm_sub_pd(_mm_mul_pd(s[0], e1[1]), _mm_mul_pd(s[1], e1[0]));
スカラコード
SSEコード
内積計算
double t;
t = ((s2[0] * e2[0]) + (s2[1] * e2[1]) + (s2[2] * e2[2])) * inv;
__m128d t;
t = _mm_mul_pd(_mm_add_pd(_mm_mul_pd(s2[0], e2[0]),
_mm_add_pd(_mm_mul_pd(s2[1], e2[1]),
_mm_mul_pd(s2[2], e2[2])), inv);
©2012 Fixstars Corporation, All rights reserved.
スカラコード
SSEコード
46
SSE化によるプロファイル結果
©2012 Fixstars Corporation, All rights reserved.
47
ステップ6. AVXによるオプティマイズ
256ビットレジスタになり、倍精度浮動小数を4並列のままで演算
することができます。
単精度-倍精度のコンバート関数を用いて変換してあげます。
FLOAT
DOUBLE
©2012 Fixstars Corporation, All rights reserved.
FLOAT
DOUBLE
FLOAT
FLOAT
DOUBLE
DOUBLE
48
Intrinsic関数によるAVX命令への書換え
外積計算
__m128d
s2[0] =
s2[1] =
s2[2] =
s2[3];
_mm_sub_pd(_mm_mul_pd(s[1], e1[2]), _mm_mul_pd(s[2], e1[1]));
_mm_sub_pd(_mm_mul_pd(s[2], e1[0]), _mm_mul_pd(s[0], e1[2]));
_mm_sub_pd(_mm_mul_pd(s[0], e1[1]), _mm_mul_pd(s[1], e1[0]));
__m256d
s2[0] =
s2[1] =
s2[2] =
s2[3];
AVXコード
_mm256_sub_pd(_mm256_mul_pd(s[1], e1[2]), _mm256_mul_pd(s[2], e1[1]));
_mm256_sub_pd(_mm256_mul_pd(s[2], e1[0]), _mm256_mul_pd(s[0], e1[2]));
_mm256_sub_pd(_mm256_mul_pd(s[0], e1[1]), _mm256_mul_pd(s[1], e1[0]));
SSEコード
内積計算
__m128d t;
t = _mm_mul_pd(_mm_add_pd(_mm_mul_pd(s2[0], e2[0]),
_mm_add_pd(_mm_mul_pd(s2[1], e2[1]),
_mm_mul_pd(s2[2], e2[2])), inv);
SSEコード
__m256d t;
AVXコード
t = _mm256_mul_pd(_mm256_add_pd(_mm256_mul_pd(s2[0], e2[0]),
_mm256_add_pd(_mm256_mul_pd(s2[1], e2[1]),
_mm256_mul_pd(s2[2], e2[2])), inv);
©2012 Fixstars Corporation, All rights reserved.
49
AVX化によるプロファイル結果
©2012 Fixstars Corporation, All rights reserved.
50
パフォーマンス最適化結果
オリジナル~AVX最適化のパフォーマンス向上の比較チャート
オリジナル性能
102.791秒
インテル® C++コンパイラー
90.458秒
11.9%削減
スカラコード最適化
75.233秒
26.8%削減
SSE最適化
47.686秒
53.6%削減
AVX最適化
39.482秒
61.6%削減
10
20
30
40
50
60
70
80
90
100
(秒)
オリジナルの処理性能と比較し2.6倍まで高速化を達成
 まだまだ改善の余地あり。
©2012 Fixstars Corporation, All rights reserved.
51
最後に
標準コンパイラからインテル® C++ コンパイラーへ
 標準コンパイラも高速だが、インテル® C++ コンパイラーは更に高速。
コンパイル・オプションだけで十分な高速化が可能。
 自動並列化オプションや自動ベクトル化オプションも有効活用しよう。
 変数への型修飾子、コンパイル・ディレクティブなども有効活用しよう。
複雑なロジックでは、ハンド・チューニングしても良い。
 一度イントリンジックで書かれたコードは保守するのはとても大変。
 仕様がフリーズした段階で高速化は行うようにしよう。
この段階でも、まだ最適化の余地あり。




レイのベクトル化、レジスタ割当、キャッシュ効率、条件分岐削除。
512ビットベクタレジスタを持つXeon Phiで動作させてみたい。
AVX2/FMA対応で更なる高速化が見込める。
次期CPUのHaswellに期待。
©2012 Fixstars Corporation, All rights reserved.
52
インテル® ソフトウェア・カンファレンス 2012
ご清聴ありがとうございました
- お問い合わせ 古坂 大地 (Daichi Furusaka)
[email protected]
http://www.fixstars.com/
@Fixstars_JP
©2012 Fixstars Corporation, All rights reserved.
Fly UP