レビューメディア「ジグソー」

Haswellマイクロアーキテクチャ進化の方向性を探る

(訂正:TVMW5でAVX2の効果を確認した)
(追加:kilifさんの記事を参考にC++でAVX2スクリプト書いてみた)
Core i7-4770K
Core i7-4770K

■ Haswellの立ち位置(あくまでも素人の視点、誤解もあるかもしれない)

Intelは、CPUのデザイン変更と生産工程の微細化(=トランジスタの増加)を交互にやっていて、今回はデザイン(マイクロアーキテクチャ)が変更になる回り。と言っても、大幅な改定じゃなくて部分的なチューニングという感じで、要するにこれからPC市場がどんどんスマホ・タブレットに書き換えられていくため、省電力に向けて最適化しようということなのかな。
プロセス・ルールとダイ・サイズ
プロセス・ルールとダイ・サイズ
SandyBridgeからIvyBridgeへの移行ではプロセスルールが32ナノメートルから22ナノメートルになってるけど、微細化された分をそのままトランジスタの増加にあててる訳じゃなくて、ダイ・サイズそのものが小さくなった。だから性能面でもそんなに大きな飛躍じゃなかったのかな。そしてHaswellではIvyBridgeよりダイ・サイズが少し大きくなっていて、プロセスルールが微細化されたことの恩恵をこうむっているように見える(トランジスタ数は14億個でIvyBridgeから変わっていないという情報もある)。

実はIvyBridgeから一番進化したのはGPUなんだけど(Iris Pro 5000系)、それは4770KのようなデスクトップモデルじゃなくてSoCやモバイル版に入ることになってる。因みに、SoCはIntel NUCと同じBGAというパッケージで始めからマザーに貼り付けてあって、自分では交換できない。一方、パフォーマンス用途には所詮内蔵グラフィックなんて使わないから、HD Graphicsで十分でしょというスタンス。それはそれで潔く、分かりやすい進化だ。

HaswellではAVX2(Advanced Vector Extensions 2.0)という新しい命令セットが導入されていて、これらバックエンド(命令実行)側のポート拡張にともなって、これを効率良く動かすために内部バッファを大きくしたり、フロントエンド(命令読み込み)でもL1/L2キャッシュの帯域を倍に拡張したり、いろいろなチューニングが施されていると考えると理解しやすいと思う。

Intel AVX2をまとめると、(1)整数演算の拡張(ALUが3ユニットから4ユニットへ増加、128ビット幅から256ビット幅命令への拡張)、(2)3オペランド積和算命令の拡張(Fused Multiply-Add即ち FMA3ユニットを2つ追加するとともに浮動小数点に拡張)、(3)BMI(Bit Manipulation Instructions)命令の追加を含んでいて、要するに並列度が上がった。それに合わせて、大規模なマルチスレッドタスクでメモリ管理をハードウェアサポートするトランザクションメモリというのも売りの一つらしいけど、これが関係するのは今年後半に出る8コアのHaswell-Eシリーズ以降かな。

それで、「結局AVX2で何を動かすんだ」ということになるんだけど、Intelの公式データシートによれば、「Intel AVX2は、Intel AVXの命令セットから256ビット整数演算、浮動小数点積和演算(FMA)、ギャザー命令(gather operations)を拡張したものになる。256ビット整数ベクトルは計算、コーデック、映像、デジタル信号プロセシングソフトが恩恵を受ける。FMAは顔認証、プロフェッショナル・イメージング、高性能コンピューティング(HPC)のパフォーマンスを改善する。ベクトルギャザー命令は多くのアプリでベクトル化を補助する。ベクトル拡張のほかに、新しく加えられたビット操作命令(Bit Manipulation Instructions)も、圧縮、暗号化、汎用ソフトの役に立つ。」ということらしい。つまり、これらのアプリケーション分野がIntelがHaswellで目指そうとしている世界だ。また、コンパイラでは既にGCC 4.7からHaswell対応になってて、科学計算方面でも今回のチューニングは威力を発揮することが期待できる。。


■ これまでの代表的なベンチマーク

もう散々ベンチマークやられてて、ほんとこれ以上何をベンチしたらいいのっていうくらい。同じことしても二番煎じで面白くないし。
PC Watch(三門 修太)
マイナビ(大原雄介)
ITMedia(石川ひさよし)
Gamer.net(宮﨑真一)
Anandtech (Anand Lal Shimpi)
TechPowerUp (FireKillerGR)
Tom's Hardware (Chris Angelini)


■ 今回の課題も難しい

マイクロアーキテクチャの変更でどれくらい性能が良くなったかをレポートするという今回の宿題は、これまでのレビューを見ていると一筋縄では行かないようだ。原因の一端は、まだHaswellが出たばかりで、アプリケーションが対応していないということが確実にある。例えば、HaswellのAVX2やFMA3が威力を発揮するビデオエンコーディングでは、リリースの時期を見る限りMediaEspresso 6.7やMediaConverter 8はまだ対応していない。QSVではもうちょっとという印象だったPegasysのTVMW5が6月27日のアップデートで正式にAVX2対応を謳っているのが目を引くくらいだ。このアップデートの前に行われているTVMW5のベンチマークの結果はTVMW5の実力を反映してないから、信用してはいけない。Haswellのマイクロアーキテクチャが、今後どんなCPUを目指して開発されているのかを知るためには、きちんとHaswellに対応したアプリケーションでベンチマークする必要があると思う。


■ ハードウェア構成

今回のレビューに送って頂いたのは、Core i7-4770K。定格で最大3.9GHz、4コア8スレッドという点は、SandyBridge (2700K) やIvyBridge (3770K)と同じ。

マザーボードの方は、初期のレビューからよく使われているAsRockのZ87E-ITX。mSATAソケットを備えるので、 Intel SSD 525がそのまま使える。Z87チップセットを選んだ理由があって、Dynamic Storage Acceleratorが使えるから(下記ベンチマーク)。

メモリは、2000MHzの2GB Corsair CMT4GX3M2A2000C8を2枚。 このITXマザー、3000MHzまでサポートするらしいので、安くなったら入れてみたい。
Z87E-ITX
Z87E-ITX

Windows 7 32ビットを入れて、Windows Experience Indexはこんな感じ。64ビットじゃないところで、少しベンチの足を引っ張ってるところがあるかも知れない。
エクスペリエンスインデックス
エクスペリエンスインデックス



■ CPUベンチマーク

HaswellはIvyBridgeとソケットが変わったため、違うプラットフォームで比較してもチップセット回りの影響がベンチマークにどう出るか分からないなあということで、Haswellの中でAVX2があるのとないのとでどれだけ差が出るかという観点からいろいろベンチ比較してみた(もちろんプラットフォームを含めた総合性能ということで比べても良いんだけど、それはもうやり尽くされてるから)。

1.SiSoftware Sandra Lite 2013 SP4 19.50
Sandraの拡張機能設定メニュー
Sandraの拡張機能設定メニュー
プロセッサ性能で、AVX2とFMA3の設定を有効・無効に切り替えてテストした。
Sandra Lite 2013 Multi-Media Native(上段)、Multi-Media .NET(中段)、General Computing Native(下段)
Sandra Lite 2013 Multi-Media Native(上段)、Multi-Media .NET(中段)、General Computing Native(下段)
結果を見ると、一番上がMulti-MediaのNativeスコアで、AVX2のスイッチを入れるとIntegerが1.6〜1.7倍に跳ね上がることが分かる。FMA3を入れるとFloatとDoubleに効いて、スコアが約1.25〜1.28倍に伸びる。これは、HaswellのAVX2が整数演算SIMDの拡張であること、Fused Multiply-Addで浮動小数点演算がサポートされたことを反映していて、Haswellの進化を一番忠実に見ることができる。中段の仮想マシン(.NET)におけるMulti-Mediaスコアや、下段のプロセッサ性能(Processor Arithmetic)では、AVX2とFMA3は何の影響も及ぼしていない。因みに、SandyBridge世代のCore i3のスコアは、Integer 95 MPix/s, Float 135 MPix/s, Double 77 MPix/s, Float/Double 102 MPix/sというレベルなので、AVX2とFMA3で活入れしたHaswellはSandy BridgeのCore i3からするとそこそこに速い。

2.TMPGEnc Video Mastering Works 5.4.0.100

アップデートでAVX2に対応したという話を見つけて、早速試してみた。オプションの環境設定を開くと、確かにCPU/GPUにAVX2が追加されている。
オプションからCPU/GPU設定
オプションからCPU/GPU設定

(※以下修正済み)
約2分のTVドラマtsファイルをMPEG-4 AVC, 720x480, 29.97fpsに圧縮変換した。 映像エンコーダのプルダウンメニューで、Intel Media SDK Hardware (QSV), Intel Media SDK Software, x264の3つから選択して、変換に要した時間を記録。画質は見てない。
映像エンコーダの指定
映像エンコーダの指定

AVX2で結構速くなってる
AVX2で結構速くなってる

Intel Media SDK Hardwareとx269を使った変換で、AVX2有りとAVX2なし(=AVX)の差が出ている。それぞれ23%と20%の時間短縮になってるから、結構AVX2が効いてるってことだ。Pegasysやるじゃん。Intel Media SDK SoftwareではAVX2の効果が全然見られないから、こっちのエンコーダはまだAVX2に対応したコンパイラを使ってないってことかな。

3.GCC 4.7

GCCは2012年3月にリリースされたバージョン4.7.0で既にAVX2、Haswellに対応している。
完全に対応したのは、4.8かららしい。

Linuxをインスコしようと思っていろいろやってみたけど、インスコまでは進むのに正常にシャットダウン・再起動しなくて、まだ動かせない。もしかすると、Haswellの新しい電源管理とか省電源モードに、まだドライバが対応してないんじゃないかと思う。もしHaswellで64ビットLinuxが動いたら、このベンチマークをやってみたい。

4.Intel C++コンパイラ(体験版)

という訳でGCCが使えないので、代わりに、kilifさんの記事を参考に、32ビットWindowsにIntel C++ Compiler評価版をインスコして、AVX2をベンチマークしてみることにした。

HaswellのAVX2とFAM3の新しい拡張機能の速度を自分で体感したくて、アセンブラはま、無理としても、C++スクリプトなら書けるんじゃないか思って始めてみたんだけど、実はC++はさわったことないくせに甘く見ていた。大昔にかじったことのあるC言語と基本的には違わないだろうと思ってたら、結構ハードル高いっす orz... そもそも、AVX2を動かすためのまとまった(サルでも分かるレベルの)情報が少ない。

IntelのC++コンパイラをインスコすると、MicrosoftのVisual StudioのGUIに組み込まれるようになってるんだけど、これがまた素人には理解不能。何でdefaultのメイン関数がtmainなのって。これは否応もなく、コマンドラインツールを使うしかない。

紆余曲折を経てたどりついた、AVX2の拡張機能を動かすためのポイントは、二つ。

(1)なんだ、組み込み関数(intrinsicという)を使えばいいんじゃん。
__m256 _mm256_add_ps(__m256 a, __m256 b); 単精度加算
__m256 _mm256_mul_ps(__m256 a, __m256 b); 単精度乗算
__m256 _mm256_fmadd_ps(__m256 a, __m256 b, __m256 c); 単精度関和演算
__m256d _mm256_add_pd(__m256d a, __m256d b); 倍精度加算
__m256d _mm256_mul_pd(__m256d a, __m256d b); 倍精度乗算
__m256d _mm256_fmadd_pd(__m256d a, __m256d b, __m256d c); 倍精度積和演算

(2)コンパイラ・オプションでHaswellを指定するやり方が分かった。
icl /O3 /QxCORE-AVX2 main.cpp
/Qxの他のオプション(Sany Bridge: AVX, Ivy Bridge: CORE-AVX-I)

組み込み関数って言うのは、例えば
  d = a * b + c;
っていう計算をする代わりに、
d = _m256_fmadd_sd(a, b, c);
っていう風に、ちょっと長い名前の関数がもう用意されてるってこと。しかも、この関数が受け取るのは256ビット幅(32ビットの単精度数なら8個、64ビットの倍精度数なら4個のデータが入る)ベクトルになってて、1個ずつ計算するより8〜4倍速い。あんまり種類が多いので、Intel Intrinsics Guide(組み込み関数ガイド)なんてアプリが配布されてるくらいだ。
組み込み関数辞典
組み込み関数辞典


kilifさんと同じ要素1000個の1次元配列3つの積和演算を、2x10^7回繰り返して比べてみた。

うーん、AVXとFMA3はスカラーより速いけど、AVXとFMA3の間には差が無い。packed data型に配列要素をロード・ストアするために組み込み関数を使っているのが影響しているのかも知れない。

(※ここから訂正)スカラー演算はコンパイラの自動ベクトル化を抑制すると遅くなったので、全体として理解しやすい結果になった。AVXとFMA演算はデータのロード・ストアをデータ型のキャストで行うより、組み込み関数で明示的に行う方が効率が良さそうだ。ただ、それにしても、コンパイラによってSIMD化されたスカラー演算の方がデータ型をキャストしたFMA3より速くなる理由が謎だ。
IntelC++コンパイラの不思議な挙動
IntelC++コンパイラの不思議な挙動
横軸はミリ秒、Vectorizeとはコンパイラの自動ベクトル化あり、Suppressedはコンパイラの/Qvec-オプションで自動ベクトル化を抑制した場合。コンパイラによるベクトル化については、この辺り(iSUS)が分かりやすい。コンパイラがどこをベクトル化しているかは、/Qvec-report1オプションで表示される。下のコードの場合、データの初期値設定とスカラー乗算・加算のループがそれぞれSIMD化される。

#include <stdio.h>
#include <immintrin.h>
#include <windows.h>
#include <mmsystem.h>
#pragma comment(lib,"winmm.lib")

static const size_t delay = 20000000; //repeat number
static const size_t n = 1000; //dimension of the data array
static const size_t align = 32;
static const size_t double_size = 4;
static const size_t nd = n / double_size;
static const size_t skip = n / 17;

int main(void){

unsigned long time0, time1;
timeBeginPeriod(1);

double* a = (double *)_mm_malloc(n * sizeof(double), align);
double* b = (double *)_mm_malloc(n * sizeof(double), align);
double* c = (double *)_mm_malloc(n * sizeof(double), align);
double* d = (double *)_mm_malloc(n * sizeof(double), align);

__m256d *va = (__m256d *)a;
__m256d *vb = (__m256d *)b;
__m256d *vc = (__m256d *)c;
__m256d *vd = (__m256d *)d;

for (size_t i=0; i<n; ++i){
a[i] = 2 * i;
b[i] = 2 * i;
c[i] = 3 * i;
}

//Mock
for (size_t i=0; i<n; ++i)
d[i] = 0.0;
time0 = timeGetTime();
for (size_t j=0;j<delay;++j)
for (size_t i=0;i<n;++i){}
time1 = timeGetTime();

printf("\nmock: time = %i msec\n", time1-time0);
for (size_t i = 0; i < n; i += skip)
printf("%.1f ", d[i]);


//Scalar multiply-add
for (size_t i=0; i<n; ++i)
d[i] = 0.0;
time0 = timeGetTime();
for (size_t j=0;j<delay;++j)
for (size_t i=0;i<n;++i)
d[i] = a[i] * b[i] + c[i];
time1 = timeGetTime();

printf("\ndouble, scalar: time = %i msec\n", time1-time0);
for (size_t i = 0; i < n; i += skip)
printf("%.1f ", d[i]);


//Vector multiply-add with data loading/storing by intrinsics
for (size_t i=0; i<n; ++i)
d[i] = 0.0;
time0 = timeGetTime();
for (size_t j=0;j<delay;++j)
for (size_t i= 0;i<n;i += 4){
__m256d a_i = _mm256_load_pd(&a[i]);
__m256d b_i = _mm256_load_pd(&b[i]);
__m256d c_i = _mm256_load_pd(&c[i]);
__m256d d_i = _mm256_add_pd(_mm256_mul_pd(a_i, b_i), c_i);
_mm256_store_pd(&d[i], d_i);
}
time1 = timeGetTime();

printf("\ndouble, vector, intrinsics: time = %i msec\n", time1-time0);
for (size_t i = 0; i < n; i += skip)
printf("%.1f ", d[i]);


//Fused multiply-add with data loading/storing by intrinsics
for (size_t i=0; i<n; ++i)
d[i] = 0.0;
time0 = timeGetTime();
for (size_t j=0;j<delay;++j)
for (size_t i= 0;i<n;i += 4){
__m256d a_i = _mm256_load_pd(&a[i]);
__m256d b_i = _mm256_load_pd(&b[i]);
__m256d c_i = _mm256_load_pd(&c[i]);
__m256d d_i = _mm256_fmadd_pd(a_i, b_i, c_i);
_mm256_store_pd(&d[i], d_i);
}
time1 = timeGetTime();

printf("\ndouble, FMA, intrinsics: time = %i msec\n", time1-time0);
for (size_t i = 0; i < n; i += skip)
printf("%.1f ", d[i]);


//Fused multiply-add with data loading by pointer casting
for (size_t i=0; i<n; ++i)
d[i] = 0.0;
time0 = timeGetTime();
for (size_t j=0;j<delay;++j)
for (size_t i= 0;i<nd; ++i){
vd[i] = _mm256_fmadd_pd(va[i], vb[i], vc[i]);
}
time1 = timeGetTime();

printf("\ndouble, FMA, casting: time = %i msec\n", time1-time0);
for (size_t i = 0; i < n; i += skip)
printf("%.1f ", d[i]);


_mm_free(a);
_mm_free(b);
_mm_free(c);
_mm_free(d);

return 0;
}
(調査中)


■ SATA高速化ツール(ダイナミック・ストレージ・アクセラレータ)

Haswell世代のチップセットとしてZ87を選ぶ理由がこれ。SATAへのアクセス負荷に応じて、I/Oスループットを最大化するというもの。Dynamic Storage Accelerator (DSA)は、Intel Rapid Storage Technology (RST)のバージョン12.0.0.1083でサポートされている。Z87の他、QM87、HM87、Q87の各チップセットでも対応している。H87はダメっぽい。
ダイナミック・ストレージ・アクセラレータとは
ダイナミック・ストレージ・アクセラレータとは

DSAを利用する手順は、
(1)BIOSのAdvancedメニューからストレージ・コンフィグレーションでDSAをEnabledにする
BIOSからDSAをEnabledに
BIOSからDSAをEnabledに

(2)コンパネの電源オプションで高パフォーマンスに設定する
コンパネ・電源オプション
コンパネ・電源オプション

(3)デスクトップ右下のインジケータ(上三角)内のRSTアイコンを右クリックしてアプリケーションを開き、パフォーマンス・メニューからダイナミック・ストレージ・アクセラレータの有効化をクリック
ラピッド・ストレージ・テクノロジのメニュー
ラピッド・ストレージ・テクノロジのメニュー

(4)DSAの設定で、自動または手動の(省電力ギア・バランス・高パフォーマンス)を選択する
ダイナミック・ストレージ・アクセラレータの設定
ダイナミック・ストレージ・アクセラレータの設定

期待しつつ、Intel謹製SSD 520 (240GB)をCrystalDiskMark3でベンチマーク。
おぉ、少しだけど速くなってる
おぉ、少しだけど速くなってる
先行記事に依ると25%もの高速化が得られると書いてあったけど、Intel SSD 520 (240GB)で試したところ3−7%程度の伸びだった。ランダムデータでも0Fillでも、またリードもライトも、確かに速度が上がっている。シーケンシャルの方が、ランダムアクセスより効果が出やすいようだ。パフォーマンスと引き換えに電力消費も上がるということだけど、デスクトップなら関係ないよね。


■ ここまでのまとめ

いろいろなレビューでHaswellの進化が限定的だと言われていて、何をベンチマークするか迷ったんだけど、解釈には注意が必要だと思う。Haswellが出てまだまだ日が浅いので、そもそもHaswellの拡張機能に対応してないアプリも多いようだし、また対応していると言っても最適化されているとは限らない(例えば計算アルゴリズムをFused Multiply-Addが使える形にするとかかな)。

簡単なベンチマークで、整数演算SIMDや浮動小数点積和演算の拡張がマルチメディア処理に確かな進化をもたらしていることが見えていると思う。考えてみると文書作成やWebブラウジングには今のCPUは既にオーバースペックなんだから、Intelがマルチメディアにフォーカスするのは理にかなってるんだろう。これが科学計算にも役に立ってくれたらいいなと思う。

4770Kのパフォーマンスについて、不思議と言うか、興味深い現象は、高負荷時の4770Kの消費電力がIvyBridgeより決して低くなっていないということだ。Haswellが低消費電力を目指しているにもかかわらずだ。これは何を意味しているのかというと、Haswellが言うところの低消費電力って、単にCPUを遊ばせてるだけじゃないのかって。Haswellは、使われていないアイドリング時の待機消費電力が圧倒的に低くなってるのは良いとして、負荷がかかってる時もわざとスロットルを絞ってターボブーストが掛からないようにしてるんじゃないだろうか(それでもIvyBridgeなみの性能が出るんだけど)。だって、IvyBridgeと比べてHaswellはマイクロアーキテクチャが拡張されてて、その分ダイ・サイズも大きくなってるんだから、消費電力が下がる方がおかしい。

という訳で、気になってるのがBIOSのAdvancedメニューにあるCPUコンフィグレーションのCPU Thermal Throttling(CPU温度制御)というスイッチ。これは、CPUがオーバーヒートしないように、一定の負荷が掛かるとクロックか電圧を下げるように作ってあるんだと思う。だから、このスイッチをオフにするか、CPUクーラーをいいやつに代えてCPU温度が上がらないようにしてやるだけで、ベンチマークが良くなるんじゃないかと思う。それと、Haswellではターボブーストのアルゴリズムも変わってるようだから(Turbo Boost Technology 2.0)、負荷、消費電力、コア温度とからどういう風にパフォーマンスと消費電力のバランスをとっているかということが、ベンチマークにも影響すると思う。
Desktop 4th Gen Core Processorデータシートからターボ・ブーストと温度管理の話
Desktop 4th Gen Core Processorデータシートからターボ・ブーストと温度管理の話

IvyBridgeまではIntelのターボ・ブースト・テクノロジ・モニタっていうアプリがあって、ぐりぐりブーストが掛かってるのを見ることが出来たんだけど、何故かHaswellには対応してないってことになってる。何で見せてくれないんだろう。(調査中)


■ QSVベンチマーク(調査中)

AVX2の効果を見るためにTVMW5をベンチマークしたので、他の定番ソフトもQSVをチェックしてみた。Haswell世代ではQSVもバージョン2.0と新しくなってるはずなんだけど、何が進化したのか詳しい資料がナカナカ見つからない。

・TMPGEnc Video Mastering Works 5.4.0.100(Pegasys 体験版)
・Media Converter 8.0.016(ArcSoft 体験版)
・MediaEspresso 6.7(Cyberlink 体験版)(アップデート)

15分46秒のTVドラマtsファイル(28374フレーム)を、MPEG-4 AVC 720x480, 29.79 fps, プロファイルMain, Level 4, 4Mpsで変換した結果を、フレーム/秒(fps)で表した。
HaswellでQSV速度比較 fps(大きい方が高速)
HaswellでQSV速度比較 fps(大きい方が高速)

上から3つは、TVMW5のx264、QSV (Intel Media SDK Hardware)、Intel Media SDK Softwareで、CPUベンチマークで見た通りQSVが一番速い。次のMediaEspresso 6.7は、QSVをオンにして測定。一番下の二つはMediaConverter 8で、どちらもQSVはオンにしてあって、上はGPUを使う、下はGPUを使わないという設定。ただし、ディスクリートGPUは挿してないので、CUDAじゃない。内蔵GPUでもGPGPU出来るってことか。

一番高速だったのは、GPUとQSVを使ったMediaConverter 8だった。僅差でMediaEspresso 6.7が続く。こいつらはTMPGEncと比べて13倍というとてつもない開きがある。画質はまだ見てないので、ブロックノイズとかチェックする必要があるけど、それにしてもMediaConverterもMediaEspressoもHaswellのAVX2には対応してないはずなんだけどな。どうなってるんだ、一体。


■ 謝辞

Intelさん、zigsowさん、最新のCPUを試す機会を頂き有難うございました。いろいろ革新的な技術が詰まっていて、素人なりに理解できる範囲でも大変楽しませて頂きました。

コメント (7)

  • kilifさん

    2013/07/12

     色々な角度からの検証おつかれさまです。ご参考いただいたとのこと、恐縮です。

     ロード、ストアが怪しいというところですが、sorrowさんのコードだとループ内で4要素ごと__m256d型に代入していると読み取れます。私のコードだとループの前に配列全体を__m256d型にキャストしています。具体的には↓のコードで、aが元のdouble型配列、a2が__m256d型配列です。

    __m256d *a2 = (__m256d *)a;

     これをやるとループ内を演算だけにできます。ネット上からの見よう見まねですが、ご参考ください。
     自信がないので一部しか載せなかったのが本音ですが、帰ったら私のソースコード全体も記事に追加かダウンロードできるようにしようと思います。

     VisualStudioについてはプロジェクト作成時に"空のプロジェクト"を選択するとメイン関数のソースファイルだけでコンパイルできます。そうしないと変なヘッダーファイルなどが出てきてややこしいです。よろしかったらお試しください。
  • sorrowさん

    2013/07/12

    kilifさん

    有難うございます。kilifさんのスクリプトがヒントになって、いろいろ勉強させて頂き、とても楽しかったです。

    わりと簡単そうだなと思って始めたのですが、いやいや、現代の高度化されたC++コンパイラは、とても付け焼刃では・・・

    ポインタのキャスティングは、きれいな方法なので、はじめそうしていたのですが、どうも挙動不審で、止めました。

    一方の組み込み関数を使ってロード・ストアするやり方は、状況によってはコンパイラの動きを明示的に指定するという意味があるのかなと解釈しています。キャスティングした場合でも、データをレジスタにロードしなければならないことは同じなので、コンパイルした後の実際のインストラクション・コードは大差ないのかなと想像してました。実際に計算に掛かった時間は、AVXとFMAで1.3秒程なので、kilifさんの結果とそんなに違わないようです。

    Multiply-addを2ステップでやるのと、FMA3を使って1ステップでやるのは、レイテンシが8対5サイクルの違いがあるはずなので、kilifさんのような結果になって欲しかったんですけどね。
  • kilifさん

    2013/07/13

    sorrowさん

    こちらの記事でもひとまずFMA3のコードを載せたのでよろしければご覧ください。

    sorrowさんのコードをこちらでもやってみたところ、sorrowさんの記事と同様にほぼ同じ実行時間で、数%程度の差しか出てきませんでした。ですが時間はスカラーが10.5秒程度、AVX,FMAが2.8秒程度とsorrowさんの結果よりも2倍以上遅くなってしまいました。

    私の記事のコードだと同じ条件で3.3秒、3秒となりましたが、キャストする方法だと何らかのオーバーヘッドが生じて、明示的にロード・ストアする場合よりも1ステップあたりの差が大きくなったというところでしょうか。キャスト時の挙動が怪しいというのは、配列要素を指定することでロード・ストアがコンパイラ任せになるとのご指摘と併せて的確と思います。

    また、ベクトル化ガイドによるとO2以上の最適化では自動ベクトル化が働くそうなので、コンパイル時に/Qvec-のオプションがないとスカラー演算が勝手にベクトル化されそうです。スカラーの差異はそこかと考えます。

    こちらは最初のメモリ確保もmm_mallocを使わないで静的にa[1000]のようにやっているのですが、それも問題になるのでしょうか。

    当方も普段C++のような細かい言語を使わないので早計な結論だった気がします。ロード・ストアなんかは全く気にしてもいませんでした。アセンブラコードを直接見ると分かるのでしょうが・・・
他4件のコメントを表示

ZIGSOWにログインするとコメントやこのアイテムを持っているユーザー全員に質問できます。

YouTube の動画を挿入

YouTube の URL または動画の ID を入力してください

動画の ID が取得できません。ID もしくは URL を正しく入力してください。

ニコニコ動画の動画を挿入

ニコニコ動画の URL または動画の ID を入力してください

動画の ID が取得できません。ID もしくは URL を正しく入力してください。

ZIGSOWリンク挿入

検索対象とキーワードを入力してください

    外部リンクを挿入

    リンク先の URL とタイトルを入力してください

    URL を正しく入力してください。

    画像を挿入(最大サイズ20MB)

    画像を選択してください

    ファイルサイズが20MBを超えています

    別の画像を追加

    ほかのユーザーのレビュー

    ZIGSOW にログイン

    ZIGSOW会員登録(無料)はこちらから