Ryzenシリーズベンチをまとめてみた

Zen3 こと Ryzen 5000 シリーズが発売となり、ベンチマーク記事を読んでいる。
特に、大原雄介氏の記事は理路整然としていて非常に参考になる。

以下の2つの記事で、Zen3 / Zen2 / Comet Lake(10th Gen) の比較と Zen2 / Zen+ / Coffee Lake(9th Gen) の比較を行っている。

記事① news.mynavi.jp

記事② news.mynavi.jp

共通して計測している項目をまとめてみた。

前置き

  • ①(薄い灰色)と②(濃い灰色)でハードウェア構成は異なる f:id:Onswar:20201106230329p:plain

    • 5900X, 3900XT, 3900Xが 12C/24T
    • 5800X, 3800XT, 3700X, 2700Xが 8C/16T
    • 10900Kが 10C/20T, 9900Kが 8C/16T
  • ①と②でソフトウェアバージョンは異なる

  • CPUに大きく依存する項目のみ抜き出して比較

3DMark Physics/CPU Test

  • バージョン
    • ① : v2.14.7042
    • ② : v2.9.6631
  • TimeSpy / TimeSpyExtreme のみ比較

f:id:Onswar:20201106225724p:plain

Futuremark,「3DMark」に4K解像度対応のDirectX 12テスト「Time Spy Extreme」を追加。リリースは10月11日の予定

4K解像度と8コア以上のCPUをターゲットとする「Time Spy Extreme」

また,Haswellこと第4世代Coreプロセッサ以降のCPUが採用する256bit SIMD演算命令セット「AVX2」をCPUがサポートしている場合,これを利用する

CineBench R20

  • バージョンは記載なし

f:id:Onswar:20201106225736p:plain

TMPGEnc Video Mastering Works 7

  • バージョン
    • ① : V7.0.17.19
    • ② : V7.0.10.11
  • 処理の設定は同じと仮定

f:id:Onswar:20201106225748p:plain

感想

  • 同じTDP枠で5800X(Zen3), 3800XT(Zen2), 2700X(Zen+)と世代ごとに性能が改善している
  • Intel CPUの後塵を拝してきたAMD CPUが、ついに優位に立つことになった

Intel oneAPI使ってみた その2 (DPCT編)

おさらい

Intel oneAPI

似たような技術にNVIDIA CUDAAMD ROCmがある

Intel oneAPIにはCUDAソースから移行するためのツール Data Parallel C++ Compatibility Tool(DPCT) が用意されている

DPCTの使い方

DPCTは、開発・実行環境であるIntel oneAPI Base Toolkitに含まれている
DPCTを使うには移行したいアプリのCUDAソースの他に、CUDAランタイムヘッダーが必要

注意
2020/10/10現在最新のIntel oneAPI Base Toolkit beta09は、CUDA11.1に対応していません
以下ではCUDA10.2を使っています

VS2019での例

シンプルなCUDAプロジェクトをDPC++プロジェクトに移行する手順

  • プロジェクトウィザードでCUDAプロジェクトを作成

    f:id:Onswar:20201010012648p:plain
    CUDAプロジェクトの新規作成

  • Migrate Project to DPC++メニューを選択

    f:id:Onswar:20201010013059p:plain
    DPC++への移行メニュー

  • 移行したいCUDAプロジェクトファイルの指定

    f:id:Onswar:20201010013523p:plain
    移行するプロジェクトの指定

  • Additional optionsにCUDAランタイムヘッダーがあるディレクトリを指定

    f:id:Onswar:20201010013735p:plain
    コンフィグ設定

ex) --cuda-include-path="C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v10.2\include"

#include <CL/sycl.hpp>
#include <algorithm> /* INSERTED */
#include <dpct/dpct.hpp>

#include <stdio.h>

int addWithCuda(int *c, const int *a, const int *b, unsigned int size);
...
  • ビルド・実行
    f:id:Onswar:20201010015344p:plain
    kernel 実行結果

IntelプロセッサーのグラフィックスアーキテクチャーにおけるDPC++

どのように計算集約型コードをIntel GPUにオフロードするか

本記事は以下の翻訳です。 techdecoded.intel.io

Intelプロセッサーのグラフィックスアーキテクチャーは多くのIntel SoC製品においてグラフィックス、コンピュート、メディアとディスプレイ能力を与えるIntelのテクノロジーです。 Intelプロセッサーのグラフィックスアーキテクチャーはgeneration(世代)を短くしたGenとして、非公式な呼び方ですが知られています。 アーキテクチャーのリリースごとにGenの後に対応するバージョンが記載されます。 例えば、Intelグラフィックスアーキテクチャーの最新リリースはGen11です。 何年にもわたって洗練されたグラフィックス(3Dレンダリングとメディアパフォーマンス)と最大1TFLOPSの性能を持つ汎用計算能力を持つまでに進化しています。

この記事では、IntelプロセッサーのGen9とGen11グラフィックスアーキテクチャーの汎用計算能力とIntel oneAPI Base ToolkitにあるData Parallel C++(DPC++)を使ってどのようにプログラムするのかについて探っていきます。 特に、DPC++を使って2つのGenアーキテクチャのプログラミングと性能の側面を示すケーススタディを見ていきます。

Intelプロセッサーのグラフィックス:世代によるアーキテクチャー外観

Intelプロセッサーのグラフィックスは、Intel CPUのダイに統合された高効率で高性能なグラフィックスとメディアアクセラレーターです。 統合GPUはCPUとラストレベルキャッシュ(LLC)を共有しており、細粒度で低いレイテンシーと高い帯域幅でのコヒレンシーなデータ共有が可能です。 図1はGen11グラフィックスがあるSoCを示しています。オンダイの統合はディスクリートのグラフィックスカードより低い電力消費を可能にします。

https://simplecore-ger.intel.com/techdecoded/wp-content/uploads/sites/11/dpc_figure1.jpg
図1:IntelプロセッサーのGen11グラフィックスSoC(CPU SoCより大きい部分)

図2はGen9GPUのアーキテクチャーブロックダイアグラムを示します。GPUは多くの実行ユニット(EU)を含み、それぞれはSingle Instruction Multiple Data(SIMD)計算を行う能力があります。 8つのEUの集まりはサブスライスとなります。

サブスライスは以下を持ちます。

これらのサブスライスが集まってスライスを形成し、スライスは(CPUとコヒレントな)共有L3キャッシュとバンク構成の共有ローカルメモリー(SLM)から構成されます。 Intelの統合GPUは1つかそれ以上のスライスを持つかもしれません。 このようなコンフィギュレーションでは、L3はインターコネクトファブリックを通して複数のスライスと接続されています。

https://simplecore-ger.intel.com/techdecoded/wp-content/uploads/sites/11/dpc_figure2.jpg
図2:Intel Gen9 GPUアーキテクチャ

図3はGen9アーキテクチャーにおけるEUのある程度の詳細を示しています。 各EUごとに最大7つのスレッドを扱えるマルチスレッディングをサポートし、各スレッドは128本のSIMD-8 32bitレジスターを持っています。 EUは1サイクルに最大4命令を発行できます(Intel GPUアーキテクチャーの詳細とベンチマークのより詳しい内容はここにあります)。例えば、ハードウェアの理論上のピークGFLOPSは以下のように計算できます。

(EUs) * (SIMD units/EU) * (FLOPS per cycle/SIMD unit) * (Freq GHz)

https://simplecore-ger.intel.com/techdecoded/wp-content/uploads/sites/11/dpc_figure3.jpg
図3:サブスライスとEUアーキテクチャー詳細

GPUのようなデバイスをプログラミングするとき、最も良い性能を得るには利用可能なハードウェア機能を上手くマッピングするプログラミング言語構成が必要です。いくつかのAPIが利用できますが、ここではoneAPIを掘り下げていきましょう。

oneAPIとDPC++

oneAPIはオープンかつ無償で、そしてアクセラレーターや複数世代のハードウェアにわたって可搬性と性能を提供する標準化ベースのプログラミングモデルです。 oneAPIは様々なハードウェアターゲットにわたってコードを再利用するために、核となるプログラミング言語のDPC++を含みます。 以前の記事、oneAPIを使ったヘトロジニアスプログラミング(The Parallel Universe, 39号)で詳細を見つけることができます。

DPC++は以下の特徴を含んでいます。

  • A Unified Shared Memory:ホスト・デバイス間の簡便なメモリマネジメントが可能になります
  • OpenCLスタイルのNDRange subgroups : ベクトル化を補助するための機能です
  • 一般的なポインタや関数ポインタのサポート
  • その他、数多くの特徴

この記事でCUDAコードをDPC++に変換するケーススタディを示していきます。

ケーススタディIntelプロセッサーのグラフィックス部でのコンピュートカーネルの実行

Hogbom Clean 画像アルゴリズムについて見ていきましょう。これは電波天文学での画像で広く使われているアルゴリズムです。この画像アルゴリズムは2つのホットスポット(処理が重たい部分)があります。

  • Find Peak
  • Subtract PSF

簡潔のため、Find Peakの性能面についてフォーカスしていきます。オリジナルの実装はC++OpenMP, CUDA, そしてOpenCLがあります。ホストCPUは利用可能なときGPU上で動作するCUDA/OpenCLカーネルにオフロードします(CUDAはNVidia GPUにのみ計算をオフロードするプロプライエタリなアプローチです)。図4と5はそれぞれホストおよびデバイスコードのスニペットを示しています。

https://simplecore-ger.intel.com/techdecoded/wp-content/uploads/sites/11/dpc_figure4.jpg
図4:Find Peak のホストコード:C++とCUDA

https://simplecore-ger.intel.com/techdecoded/wp-content/uploads/sites/11/dpc_figure5.jpg
図5:Find Peakのデバイスコード:CUDA

CUDAコードを手動でDPC++コードに置き換えることもできますし、DPC++互換性ツール(DPCT)を使うこともできます。DPCTはCUDAプログラムをDPC++(図6と7)へ移行するのを補佐します。移行にはIntel oneAPI Base ToolkitとNVIDIA CUDAヘッダーのみ必要です。DPCTを起動してexample.cuファイルを移行するのは以下のようにシンプルです。

dpct example.cu

多くのCUDAファイルがあるアプリケーションの移行では、プログラムソースの場所を指定するDPCTのオプション-in-rootと移行したコードを書き込むための-out-rootが利用できます。アプリケーションがmakecmakeを使っているのなら、intercept-buildを使って移行を行うのをお勧めします。これはコンパイラ呼び出しとともにコンパイル処理のデータベースファイルを作成します(ホストC++コードとデバイスCUDAコード両方の入力ファイル名と、付随するコンパイラオプションです)。

intercept-build make
dpct -p=<path to .json file> --out-root=dpct_output ...

特にHogbom Clean CUDAコードをDPC++に移行するのには、CUDAカーネルを持つHogbomCuda.cuファイルにDPCTツールを直接かける方法、intercept-buidを使う方法、どちらも利用可能です。デフォルトでは移行したコードはdp.cppという拡張子名のファイルが得られます。

以下に移行したDPC++コードとオリジナルのCUDAコードの比較を見ることができます。

https://simplecore-ger.intel.com/techdecoded/wp-content/uploads/sites/11/dpc_figure6.jpg
図6:DPCTを使って移行したFind Peak DPC++のホストコード

https://simplecore-ger.intel.com/techdecoded/wp-content/uploads/sites/11/dpc_figure7.jpg
図7:CUDAホストコードと移行したDPC++ホストコードの比較

https://simplecore-ger.intel.com/techdecoded/wp-content/uploads/sites/11/dpc_figure8.jpg
図8:DPCTを使って移行したFind Peak DPC++のデバイスコード

https://simplecore-ger.intel.com/techdecoded/wp-content/uploads/sites/11/dpc_figure9-1.jpg
図9:Find Peak CUDAカーネルと移行したDPC++デバイスコードの比較

DPC++コードで鍵となる側面がいくつかあります。

  • SYCLキューを使ったデバイスコードの呼び出し
  • バイスコードを実行するためのラムダ関数ハンドラー
  • マルチスレッド実行のためのparallel_for構文(オプション)

ここで、移行後のDPC++コードは単一共有メモリ(USM)プログラミングモデルを使い、デバイスカーネルによって読み書きされるデータをデバイスメモリに確保します。(ホストではなく)デバイス上のメモリ確保なので、ホストとデバイス相互の明示的なデータコピーが必要となります。また、共有としてメモリを確保し、ホストとデバイス両方がアクセス、更新することもできます。ここで示していないこととして非USMモードがあり、これはSYCLバッファーとアクセサーを使ってデータ転送を行います。

DPCTで移行したコードは実行するデバイスを決め、デバイスのためのキューを作成します(get_current_device()get_default_queue()の呼び出し)。GPUへDPC++コードをオフロードするために、sycl::gpu_selectorパラメーターを持ったキューを作成する必要があります。処理されるデータはデバイスと(そのデバイスである)GPU上で実行するカーネルで利用できるようにすべきです。GPUへ/またはGPUからコピーされるデータのサイズと次元はsycl::range, sycl::nd_rangeで指定します。DPCTを使うとき、CUDAコードの各ソース行は等価のDPC++コードに移行されます。Find Peakのデバイスカーネルコード(d_findPeak)では、(CUDAコードから)生成されたDPC++コードはほぼ1対1で等価の移行になります。なので、DPCTは素早い移植とプロトタイピングのための非常に強力なツールになります。移行したDPC++コードとCUDAコードの比較を図7と9に示します。

DPCTを使ってDPC++に移行したコードを得て、次はその正確性と効率性を検証してみます。いくつかのケースでは、DPCTツールはプリプロセッサのディレクティブ変数を対応する値に置き換えるかもしれません。この置換を手動で戻す必要があるかもしれません。また、移行したコードに修正が示されるコンパイルエラー(CUDAのthreadId.xを等価であるnd_rangeアクセサーに置き換えることなど)が起きるかもしれません。Hogbom Cleanアプリケーションコードには、移行後のDPC++コードが生成した結果の検証を手助けする正確性チェッカーがあります。正確性チェックはGPU上でのDPC++コード実行の結果と元となるホストCPU上でのC++実装の結果を比較することで行われます。

そして、移行したDPC++コードのGPU上での利用率(EU占有率やキャッシュ使用状況、単精度や倍精度のFLOPS)やホスト・デバイス間のデータ転送を解析することでその効率性を測定することができます。GPU利用率にインパクトを与えるパラメーターの1つとしてワークグループのサイズとそのrange dimensionがあります。Hogbom Cleanアプリケーションでは、Find Peak処理においてnBlocksfindPeakWidthにあたります。

性能へのインパクトとチューニングのこの機会を説明するために、nBlocksの値を24と4に設定して測定した性能プロファイルを図10に示します。 findPeakWidthは256に設定しています。このプロファイルはGPUプロファイリング機能をサポートするIntel Vtune Profilerで測定しました。CUDAを使ったNVidia GPUでの効率的なパラメータがDPC++コードを実行するIntel GPUにおいて効率的ではないかもしれないので、DPCTを使った場合チューニングはより明確に必要となります。表1はGen9(48EU)で測定した結果を示します。

https://simplecore-ger.intel.com/techdecoded/wp-content/uploads/sites/11/dpc_figure10.jpg
図10:nBlocksの2つの値 (a) 24, (b) 4 におけるGen9でのHogbom Cleanのプロファイル結果

表1:処理量の多い Find Peak におけるGen9 GPUでの性能測定
https://simplecore-ger.intel.com/techdecoded/wp-content/uploads/sites/11/dpc_table1.jpg

GPUの利用率や効率性の最適化に加えて、ホスト・デバイス間のデータ転送もまたチューニングすべき点です。Hogbom CleanアプリケーションにはFind Peak, Subtract PSFカーネルの複数回の呼び出しがあり、これらのカーネルで使われるデータはデバイス上に常駐させることができます。それゆえ、メモリの再確保やホスト・デバイス間のコピーは必要ありません(今後の記事でデータ転送と単一共有メモリに関するこれらの最適化についてお話しする予定です)。

より良いアルゴリズムを書くこと

IntelプロセッサーのグラフィックスアーキテクチャとDPC++の特徴を理解することは、より良いアルゴリズムと移植可能な実装を書くことの手助けになります。この記事では、いくつかのアーキテクチャの詳細をレビューし、DPC++を構成するものとDPCTを使ったケーススタディを見てきました。Intel GPUでの最高性能を得るために、特にDPCTを使うときはカーネルパラメーターを調整することが重要です。最新のIntelハードウェアとソフトウェアでアプリケーションの開発、テスト、実行するのにIntel DevCloudをお試しいただくことをお勧めします。

Intel oneAPI使ってみた

note.com

使っているノートPCはSkylake (6th Gen CPU, Gen9 GPU)とギリギリ Intel oneAPI 対応プラットフォームなので、
開発環境をインストールしてサンプルを動かしてみました

本記事の対象

LinuxFPGAここを見てね

インストールするもの

インストール手順

  1. GPUドライバーの更新(上記note記事にTIPSのっけてます)
  2. Visual Studio 2019を使う場合は、先にインストールとのこと(拙環境はインストール済みなので割愛)
  3. oneAPI Base Toolkitをダウンロード. アカウントがなければ先に作成
  4. oneAPI Base Toolkitをインストール. 特に操作なし

さぁ始めよう

  • やり方は以下の2種類「お好きな方をどうぞ」
  • コマンドラインベース
    • setvars.batで環境変数通してからうんぬんかんぬん
    • 大体のサンプルはCMake使う前提らしい
    • だからCMake入れようねぇと言っているが、この後のサンプルはMSBuild使ってる謎
  • VisualStudioベース
    • 拙環境だとVS2019 ver.16.5.5と>16.4だったが、ソリューションファイル読み込みでエラーが発生したのでver.16.7.3に更新したところ読み込めるようになった
      f:id:Onswar:20200919182333p:plain
      VS2019のバージョン
    • 実行結果は以下の通り
      f:id:Onswar:20200919182337p:plain
      vector-add-usm 実行結果
      • GPUで実行しているぽい

他のサンプル

他には↓のようなサンプルがある

f:id:Onswar:20200919204643p:plain
VS2019のサンプルメニュー

oneVPL(Video Processing Library)"Hello DPC++ interop" を実行してみる

f:id:Onswar:20200919204233p:plain
タスクマネージャーのGPUペイン(dpcpp-blur.exe実行時)

GPUを使っているように見える

※ソースそのままだと実行時エラーが発生したので以下のように、device.is_gpu()を有効にするよう変更しました

// Select device on which to run kernel.
class MyDeviceSelector : public cl::sycl::device_selector {
public:
    MyDeviceSelector() {}

    int operator()(const cl::sycl::device &device) const override {
        const std::string name =
            device.get_info<cl::sycl::info::device::name>();

        std::cout << "Trying device: " << name << "..." << std::endl;
        std::cout << "  Vendor: "
                  << device.get_info<cl::sycl::info::device::vendor>()
                  << std::endl;

        if (device.is_cpu())
            return 500; // We give higher merit for CPU
        //if (device.is_accelerator()) return 400;
        //if (device.is_gpu()) return 300;
        //if (device.is_host()) return 100;
        return -1;
    }
};
// Select device on which to run kernel.
class MyDeviceSelector : public cl::sycl::device_selector {
public:
    MyDeviceSelector() {}

    int operator()(const cl::sycl::device &device) const override {
        const std::string name =
            device.get_info<cl::sycl::info::device::name>();

        std::cout << "Trying device: " << name << "..." << std::endl;
        std::cout << "  Vendor: "
                  << device.get_info<cl::sycl::info::device::vendor>()
                  << std::endl;

        //if (device.is_cpu())
        //    return 500; // We give higher merit for CPU
        //if (device.is_accelerator()) return 400;
        if (device.is_gpu()) return 300;
        //if (device.is_host()) return 100;
        return -1;
    }
};

dpcpp-blur.exe

This sample is a command line application that takes a file containing a raw I420 format video elementary stream as an argument, converts it to RGB32 with oneVPL and blurs each frame with DPC++ by using SYCL kernel, and writes the decoded output to out.rgba in RGB32 format.

I420フォーマットのビデオエレメンタリーストリームをoneVPLを使ってRGB32に変換しつつ
DPC++(Data Parallel C++)で書かれたSYCLカーネルによるブラーを毎フレームかけてout.rgbaファイルに書き出す処理をしているらしい

ffplayで再生してみるとブラーかかってる(元データしらんけど)

f:id:Onswar:20200919212242p:plain
ffplayによるout.rgbaの再生結果

おわりに

8000円で買った中古ノートPCで、スパコンでも使われるソフトウェアフレームワークを試せたのは中々楽しい oneAPIのベース技術であるSYCLはベンダー固有ではないので、どっかで役に立てばいいなぁ