GPGPU - arch.cs.titech.ac.jp ·...

41
東京工業大学工学部 学士論文 GPGPU ソフトウェア シミュレータの高速化 指導教員 吉瀬 謙二 准教授 平成 28 2 提出者 学科 情報工学科 学籍番号 12 04377 氏名 川井 博斗 指導教員認定印 学科長認定印

Transcript of GPGPU - arch.cs.titech.ac.jp ·...

東京工業大学工学部

学士論文

GPGPUソフトウェアシミュレータの高速化

指導教員 吉瀬 謙二 准教授

平成28年2月

提出者

学科 情報工学科学籍番号 12 04377

氏名 川井 博斗

指導教員認定印学科長認定印

平成 27年度 学士論文内容梗概

GPGPUソフトウェアシミュレータの高速化指導教員 吉瀬 謙二 准教授

情報工学科12 04377 川井 博斗

GPUはコンピュータを構成する部品の1つであり、その本来の用途は画像処理の分野における演算装置であった。しかし、近年ではその計算性能の高さから画像処理分野のみならず流体計算やゲノム解析などの高性能計算にその演算資源を利用するGPGPUが拡大している。GPGPUの需要は今後も増加していき、その需要の増加に伴いGPGPUアーキテクチャの研究が一般的になると考えられる。アーキテクチャの研究においてはソフトウェアシミュレータを用いてその構

成を変更しシミュレーションを行うことで、構成の有用性を検証していくことが一般的である。また、GPGPUシミュレータとはプログラミング言語で記述された機能レベルまたはサイクルレベルで動作するGPGPUの動作を模倣するソフトウェアである。しかし、既存のGPGPUシミュレータには実機での実行に比べ数千から数万倍以上の時間を必要とするという問題がある。GPGPU

シミュレータの高速化は解決すべき課題の1つである。また、アーキテクチャ研究においてはシミュレーションの実行時間だけではなく、その精度も重要である。本論文では、広く用いられている GPGPU シミュレータの1つである

GPGPU-Simのシミュレーション精度を下げない高速化を目指し、様々な高速化手法について検討・実装を行う。検討を行う際は性能解析ソフトであるVtune

を用いてシミュレーションにおいて多くの時間を消費している関数を発見し、該当箇所に対して様々な高速化手法を適用する。評価では、速度向上率や性能解析結果を比較することで、適用する高速化手法の有用性について評価する。評価結果から、シングルスレッドにおける高速化と並列化により目的とした関数の速度向上に成功し、全体としてもGPGPU-Simの大幅な速度向上を達成することを明らかにする。

目 次

第1章 緒論 1

1.1 研究の目的と背景 . . . . . . . . . . . . . . . . . . . . . . . . . . 1

1.2 本論文の構成 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1

第2章 背景 3

2.1 GPGPU . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3

2.2 GPGPU-Sim . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7

第3章 GPGPU-Simの高速化手法 13

3.1 ベンチマークの性能解析 . . . . . . . . . . . . . . . . . . . . . . 13

3.2 高速化手法 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15

第4章 性能評価 22

4.1 実行結果 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22

4.2 実行結果に対する性能解析 . . . . . . . . . . . . . . . . . . . . . 27

第5章 考察 30

5.1 シングルスレッドにおける高速化手法 . . . . . . . . . . . . . . . 30

5.2 並列性 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31

5.3 関連研究 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31

第6章 結論 35

6.1 まとめ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35

6.2 今後の課題 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35

謝辞 36

参考文献 37

i

第1章

緒論

1.1 研究の目的と背景GPUはコンピュータを構成する部品の1つであり、その本来の用途は画像処

理の分野における演算装置であった。しかし、近年ではGPUの計算資源を画像処理分野だけではなく、ゲノム解析や流体計算などの高性能計算に用いるGPGPUと呼ばれる技術が広く用いられている。GPGPUの需要は今後も増加していき、その需要の増加に伴いGPGPUアーキテクチャの研究が一般的になると考えられる。アーキテクチャの研究においてはソフトウェアを用いてその構成を変更しシ

ミュレーションを行うことで、構成の有用性を検証していくことが一般的である。GPGPUシミュレータとは機能レベルまたはサイクルレベルで動作するGPGPUの動作を模倣するソフトウェアである。しかし、既存のGPGPUシミュレータには実機での実行に比べ数千から数万倍以上の時間を必要とするという問題がある。GPGPUシミュレータの高速化は解決すべき課題の1つである。また、アーキテクチャ研究においてはシミュレーションの実行時間だけではなく、その精度も重要である。本論文では、広く用いられている GPGPU シミュレータの1つである

GPGPU-Sim[1] に対し、シミュレーション精度を下げない様々な高速化手法について検討・実装を行う。検討を行う際は性能解析ソフトである Intel Vtune

Amplifier 2015[2]を用いてシミュレーションにおいて多くの時間を消費している関数を発見し、該当箇所に対して様々な高速化手法を適用する。評価では、速度向上率や性能解析結果を比較することで、適用する高速化手法の有用性について評価する。

1.2 本論文の構成本論文の構成は以下の通りである。2章において、GPUアーキテクチャや

GPGPUシミュレータについて説明を行う。3章において、ベンチマークに対す

1

る性能解析と提案する高速化手法について述べる。4章において、各高速化手法を適用したシミュレータの評価を行う。5章においては 4章の結果をもとに考察と関連研究との比較を行い、6章で結論を述べる。

2

第2章

背景

2.1 GPGPU

General-Purpose computing on Graphics Processing Units(GPGPU)とは、Graph-

ics Processing Unit(GPU)の特性を活かしながら、GPUの演算資源を高性能計算に応用する技術のことである。GPUは数百から数千個の計算コアを備えており、データレベル並列性の高い計算を行う際には、非常に高い性能を示すことができる。一方で、並列性の低い分岐命令が多いプログラムなどでは性能を発揮することができない。

AMDと NVIDIAの2社がGPUのシェアの大部分を占め、本論文では、そのうちの NVIDIAの GPUを対象とする。また、評価対象のプログラムとしては、NVIDIAの提供するプラットフォームである Compute Unified Device

Architecture(CUDA)[3] により記述されたプログラムを対象とする。提案手法の前提となるために、本節では、Fermi[4]アーキテクチャ及びCUDAについて説明を行う。

2.1.1 FermiアーキテクチャFermiアーキテクチャはNVIDIA GPUの第三世代に採用されたアーキテク

チャである。Fermiアーキテクチャの概略図を図 2.1に示す。大きく構成を分けると、DRAM、L2キャッシュ、Giga Thread Engine、ストリーミング・マルチプロセッサ(SM)の4つの部分から構成されている。DRAM、L2キャッシュはメモリ部分である。SMはプロセッサ部分に相当し、計算部分を担当をしている。Giga Thread EngineはホストCPUと接続を行いながら、スレッドの管理を行っている。

SM1個あたりの構造は図 2.2に示す。SMには4つの実行ユニットがあり、CUDAコア 16個が2組、Load-Store Unit(LDSTユニット)が 16個 1組、Special

Function Unit(SFUユニット)が 4個 1組から成り立つ。CUDAコアは分岐命令・浮動小数点数演算を含む基本的な命令を処理するコア、LDSTユニットはロー

3

図 2.1: Fermiアーキテクチャの概略図

図 2.2: ストリーミング・マルチプロセッサ

4

ド・ストア命令を処理するユニット、SFUユニットは正弦や平方根など超越関数命令を取り扱う計算ユニットとなっている。

SMでは単一命令複数スレッド(Single-Instruction Multiple-Thread、SIMT)

アーキテクチャを採用しており、同一命令を複数スレッドで用いる。各CUDA

コア、LDSTユニット、SFUユニットはそれぞれ同一の命令を実行するが、レジスタファイルは個々のスレッドに割り当てられるため、一度に別々のデータを処理することができる。各SMには2つのワープスケジューラユニットが存在しており、各スケジュー

ラユニットがCUDAコア、LDSTユニット、SFUユニットのいずれかの組に対してワープを発行する。ワープとは全て同一命令である 32本のスレッドの集まりを表す。SMのワープ 1つあたりの実行はCUDAコア、LDSTユニットではコアが 16個ずつであるため 2サイクルを、SFUユニットではコアが 4個であるため8サイクルかけて処理を行う。1サイクルに最大で 2ワープを発行することができるため、理論的には最大で 1ワープを 1サイクルで処理することができる。

2.1.2 CUDA

CUDAとはNVIDIA GPU向けのプラットフォームである。NVIDIAが提供するライブラリを使用することにより、C/C++のプログラムからGPUを使用することができる。GPUで実行する関数はカーネル関数と呼ばれる。カーネル関数を呼び出す際は func gpu ≪ block, thread ≫ の形式で blockと threadの値を指定する。ここでの、block とは Corporative Thread Array(CTA,またはThread Block)の数、threadとは 1CTA内のスレッド数である。CTAはプログラマが指定したスレッドのまとまりであり、FermiアーキテクチャではCTA内スレッド数の上限は 1024と定められている。

CUDAプログラムをコンパイルして生成される実行ファイルには、GPUのネイティヴコード (SASS)に加えてParallel Thread Execution (PTX) Instruction

Architecture と呼ばれる仮想命令セットアーキテクチャ形式の命令列が含まれる。プログラムを実行する際には、コンパイルされた SASSを実行するが、これは実際のGPUのアーキテクチャによっては実行できない。その場合、ライブラリがPTX命令列をそのアーキテクチャに適した SASSに実行時にコンパイルして実行する。仮想命令セットアーキテクチャを介することにより移植性を高め、異なるGPUアーキテクチャにおいても実行可能となっている。実際にGPUが計算を実行する場合、図 2.3のような形でGPU内にあるGiga

Thread Engineが各 SMに対してCTAを発行し、各 SMが発行されたCTAに対し処理を行う。そして、各 SMは CTAからワープに分割する。SM内のスケジューラユニットは各コア、ユニットに対してワープを発行する。各コア、ユニットはワープ内のスレッドにもとづいて計算を行う。CTAの処理が終わった

5

SMに対してはGiga Thread Engineが再びCTAを発行することで、順次計算を行うことができる。

図 2.3: スレッドの割り当てとワープ

6

2.2 GPGPU-Sim

2.2.1 概要GPGPU-Sim[1] はC++で記述された機能レベルまたはサイクルレベルで動

作するGPUシミュレータであり、ランタイムライブラリの形で実装されている。本来のライブラリを置き換えることにより、CUDAやOpenCLのプログラムをそのまま実行しシミュレーションをすることができる。OpenCLはNVIDIA

GPUとAMD GPUのどちらにも利用可能なクロスプラットフォームなフレームワークである。

GPGPU-SimではGPU部分のみのシミュレーションを行い、CPU部分は行わない。CUDAプログラムをシミュレーションする場合、PTX形式の命令列をそのまま実行するモードと SASSに対応する命令列を実行するモードを行うものがあるが、本論文では前者を用いる。シミュレーション環境としてアーキテクチャはNVIDIAのGPU、特にFermiアーキテクチャをターゲットとしており、SMの数やキャッシュサイズ等を変更することができる。機能レベルのシミュレーションでは、実行サイクル数などの計測は行わずに

GPUプログラムを実行し、実行命令数、シミュレーション時間、実行結果のみを得ることができる。一方でサイクルレベルの場合、機能レベルで得られるデータに加え、モデルとしたアーキテクチャにおける実行サイクル数やキャッシュのヒット率などのデータを得ることができる。

GPGPU-Sim の構成は SIMT コア、インターコネクションネットワーク(ICNT)、L2キャッシュ、DRAM の4つの領域に分かれており、それらは異なるクロックで動作する。SIMTコアとはFermiアーキテクチャの SMに相当するものである。図 2.4はGPGPU-Simにおけるシミュレーションフローである。シミュレーション 1サイクルの計算を行う関数GPGPU-Sim::cycle()の中では各クロック領域に対応した関数を順次実行している。なお、SIMTコアのシミュレーションはコアの数だけ for文を回すことによって行っている。

GPGPU-SimにはGPUWattchとAerialvisionと呼ばれる追加機能が備わっている。GPUWattchはプログラムを実行した際、対象としたGPUにおいて電力消費量を計算sる機能である。Aerialvisionはシミュレーションサイクルごとの各 SIMTコアの命令実行数などの情報を視覚的に表示する性能解析機能である。基本的にはこれらは実行時の引数によって機能を使用するかどうかを決めることができる。本論文では、これらの機能は使用しないようにする。

7

図 2.4: GPGPU-Simのシミュレーションフロー

8

図 2.5: SIMTコア内のパイプライン [5]

2.2.2 SIMTコアの処理SMが実際にどのようにワープを処理するのかはNVIDIAは公開していな

い。しかしながら、サイクルレベルのシミュレーションを行う上では SM内で実際にどのように命令を処理するかを定めなくてはならない。本節では、GPGPU-Sim中でFermiアーキテクチャでの SMにあたる SIMTコアの処理について説明を行う。GPGPU-Simでは高度にマルチスレッド化されたパイプライン Single-Instruction Multiple-Data(SIMD)プロセッサをモデルとしている。各 SIMTコアは図 2.5のように fetchステージ、decodeステージ、issueステー

ジ、read operandステージ、executeステージ、writebackステージの 6段にパイプライン化されている。

fetchステージでは I-Bufferに入っていない warpIDの命令をフェッチする。decodeステージではデコードし、I-Bufferを更新する。この時、2命令分の命令列をデコードする。issueステージでは、各スケジューラユニット (Fermiでは2つ)がワープの発行を行う。ただし、I-Buffer, Scoreboard, SIMT-Stack の値から、構造ハザードやデータハザード等の検出された場合はワープを発行せず、ストールされる。read operandステージでは命令に必要なオペランドを整える。オペランドの値は各スレッドごとに必要となるが、ワープ内のスレッドは全て同一命令を保持しているため、まとめて確保することができる。そのため、オペランドの値はレジスタバンクを用いて表現できる。レジスタバンクは図 2.6のように管理されており、Collector Unitに入った命令はその命令に必要なオペランドの数に応じて、レジスタバンクを指定する必要がある。レジスタバンクへのアクセスはアービターを通じて行われている。各サイクルごとに新たにレジスタバンクの確保が必要になった場合は、バンクへのアクセスが衝突しないか確認を行い可能であれば確保する。executeステージではそれぞれのユニット(CUDAコア 16個× 2、LDST16個、SFU4個)が各々処理

9

図 2.6: 各 SIMTコアのレジスタ管理 [5]

を行う。writebackステージではそれぞれのステージ関数の実行結果に応じて、SIMT-Stackや scoreboardの値を更新を行う。モデルとなる SIMTコアは前述のとおりであるが、実際の実装では先に述べ

た動作とは異なるパイプラインステージの動作がある。それは issueステージと read operandステージ、executeステージの 3ステージ

の処理である。issueステージではワープを発行する役割だけでなく、本来ならば executeステージで行われる命令列の計算もしている。なおこの時、ワープ内の 32スレッド分の命令を for文を用いて順に計算を行い、スレッドごとにアクティブかどうかの確認を行い、アクティブなスレッドのみ値の計算を行う。read operandステージではオペランドを整える役割があったが、実際には何も行わない。executeステージでは本来 read operandステージで行うはずであったオペランドの調整を行う。しかしながら、これらの確保も命令によって動作が異なる。ロード・ストア命令についてはこれらのバンクへ確保だけではなく、値の読み込みや書き込みを行っている。それに対し、他の命令はレジスタバンクの確保のみを行う。また命令列の計算は issueステージで行われているので、予め設定した実行に必要となるサイクル数をカウントしている。

10

2.2.3 実機とGPGPU-Simとの実行時間比本節は実機とGPGPU-Simの実行速度を比較する。表 2.1の評価環境におい

てRodiniaベンチマーク [6]のサブセットを実行し、シミュレーション時間を測定した。問題サイズは表 2.2に示すとおりである。Rodiniaベンチマークはヘテロジニアスコンピューティング向けのベンチマークであり、GPUやマルチコアCPUを対象としている。なお、GPGPU-Simのシミュレーションモデルは実機と同じ型のものである。その結果を表 2.3に示す。表 2.3より、GPGPU-Simは実機に対して、数千倍から数万倍の実行時間を必要とすることがわかる。

表 2.1: 評価環境CPU Core i7 3770K(4-core)

GPU NVIDIA GeForce GTX480

OS Ubuntu 14.04, 64bit

メモリ 16GB

CUDA 4.2

コンパイラ GCC 4.6.4

表 2.2: アプリケーションの問題サイズアプリケーション 問題サイズ

pathfinder 40000 ×100× 20

backprop 65536

dwt2d 1024 ×1024

nw 2048 ×10

表 2.3: 実機とシミュレーションの実行時間比アプリケーション 実機 (s) GPGPU-Sim(s) スローダウン

pathfinder 0.08 319 4,130

backprop 0.07 308 4,202

dwt2d 0.11 371 3,358

nw 0.09 908 10,295

11

このように大きく実行時間比が出る理由は、GPUとCPUの構成が異なっているためである。GPUは単純な計算ユニットの数がCPUよりも遥かに多い。これにより、サイクルレベルのシミュレーションを行う場合には非常に多くのハードウェアコンポーネントのシミュレーションを逐次的にCPUで行う必要があるため多くの実行時間が必要となる。

GPGPU-Simではループ文を用いて実機上では並列に動作している部分を実行している。そして、SIMT/ICNT/DRAM/L2キャッシュの各領域を実行したところで、シミュレーション時間のサイクルカウントを 1つ進めている。これにより実行に多くの時間が必要とはなるが、実機の1サイクル毎の各ユニットの状態をシミュレートをすることができ、高い精度でのシミュレーションが可能となっている。

12

第3章

GPGPU-Simの高速化手法

3.1 ベンチマークの性能解析効率的な高速化を行うため、シミュレーション上で時間がかかる処理部分

に性能解析を行った。性能解析の対象は 2.2.3節において測定を行ったRodinia

ベンチマークのサブセットであり、性能解析ソフトについては Intel Vtune

Amplifier 2015[2]を使用した。本節では、各関数のシミュレーション時間の割合を測定した結果について述べ、高速化する関数等の検討を行う。解析を行い、実行時間の割合を計算により求めた点は以下の2つである。

• ICNT/DRAM/L2キャッシュ/SIMTコアのクロック別領域

• SIMTコア領域の各パイプラインステージ

3.1.1 クロック別領域の性能解析性能解析した結果から求めた各クロック別領域の実行時間の割合を図 3.1に

示す。これより、SIMTコアがシミュレーション実行結果の大部分を占めていることが分かる。これはGPUハードウェアにおいて SIMTコアの占める割合はICNT/DRAM/L2キャッシュに対して物理的量がはるかに大きいためである。この結果より、シミュレーションの全体を効率的に高速化を行うためには

SIMTコアの計算部分を高速化することが効果が大きいと考えられる。GPUの構造上、各 SIMTコアはデータの依存が少ないため、少ない排他制御で容易かつ高性能な並列化を行うことができると考えられる。

13

図 3.1: 各クロック別領域の実行時間比率

3.1.2 SIMTコア部の性能解析さらなる高速化を図るため、SIMTコア内部における高速化箇所について検

討を行う。SIMTコアはパイプライン化されているため、その各パイプラインステージに対して性能解析を行った。その結果から求めた各パイプラインステージの実行時間の割合を図 3.2に示

す。図より、nwのベンチマーク以外では issueステージが最も割合が高いことが分かる。これは、issueステージにおいてGPGPU-Simがプログラムの実際の計算を行うためである。

nw が他と異なる性質を示し、execute ステージの割合が高い理由はInstruction Per Cycle(IPC)の大きさによる。2.2.3節のサブセットをGPGPU-Sim

を用いて実行した際の総命令数、総クロック数、IPC、総ストール数をまとめた結果を表 3.1に示す。ただし、クロック数は SIMTコアのシミュレーションにかかったサイクル数であり、総ストール数は全ワープのストール数の合計である。IPCを比較すると、nwが最も値が小さいことがわかる。一方で、nwはストール数が最も多い。命令列を実際実行する部分は issueステージであるから命令がストールされた時は issueステージの実行時間が短くなる。その結果、相対的に executeステージでの割合が高くなったと考えられる。以上より、一般的には issueステージの高速化を行うことが最も効果的である

14

図 3.2: 各パイプラインステージの実行時間比率

表 3.1: アプリケーションの統計情報アプリケーション 総命令数 総クロック数 IPC 総ストール数

pathfinder 260,233,648 362,793 717 95,842

backprop 190,054,784 335,767 566 1,885,176

dwt2d 204,918,584 1,181,722 173 2,555,656

nw 207,696,896 5,268,656 39 11,400,655

と考えられる。しかしながら、IPCの低いアプリケーションにおいては、issue

ステージだけでは効率的な性能向上が期待できない。そこで、issueステージとexecuteステージを合わせた割合はいずれのアプリケーションでも 90%以上の高い割合を占める。よって、両方のステージの高速化を検討する。

3.2 高速化手法本節では、3.1節の導いた方針から高速化手法について説明を行う。本論文

では、高速化を行った場合においても実行サイクル数等のシミュレーションを実行した際の情報に差異を生じない手法のみについて検討を行う。

15

大きく分けると次の 3点について高速化を行っている。

• SIMTコア領域のサイクルを実行する関数 (サイクル関数)の並列化による高速化

• SIMTコア内の issueステージ関数と executeステージ関数の高速化

• その他の高速化手法が適用できる関数の高速化

3.2.1 SIMTコアの並列化SIMTコア領域のサイクル関数の並列化に関して本論文ではOpenMP[7]を用

いている。

OpenMP

OepnMPとは、共有メモリマルチプロセッサ上のマルチスレッドプログラミングのための規格である。ソースコード 3.1はOpenMPを用いて並列化を行った一例である。

ソースコード 3.1: OpenMPを用いる例1 int b;2 int a[100];3 #pragma omp parallel for num threads(THREAD NUM)4 for (unsigned i=0;i<100;i++)5 {6 a[i]=0; // 並列処理される7 #pragma omp atomic8 b += i; // 並列処理させない (値を順に増加させたい)9 #pragma omp critical

10 {11 b = b + b;12 printf(”%d”, b); // 並列処理されない13 }14 }

この際、THREAD NUMは並列化したいスレッド数の値である。しかし、並列化した関数内で、複数のスレッドが共有変数への書き込みを行った場合、 複数のスレッドが共有する資源にアクセスしてしまう。このような内容を含む部分のことをクリティカル・セクションという。クリティカル・セクションに対しては#pragma omp criticalや#pragma omp

atomicを用いて同時に 1スレッドしか実行できなくする排他制御を行う必要がある。#pragma omp criticalでは直後の一文またはブロックを指定し排他制御を行う。#pragma omp atomicでは直後の一文のみを指定でき、xをスカラー変数としたときの x++, ++x, x–, –x, x+=値, x-=値, x*=値, x/=値, x&=

16

値, xˆ=値, x|=値, x<<=値, x>>=値のいずれかの式の場合の排他制御を行う。#pragma omp atomicはハードウェア命令による値の更新を行えるが、#pragma

omp criticalではできないため、#pragma omp criticalより効率がよく可能な限り#pragma omp atomicを利用する。ソースコード 3.1では、配列 aの代入は並列に処理されるが、#pragma omp

atomicで指定された bへの加算は排他制御される。

実際の適用

3.1.1節で述べたように、SIMTコア同士の依存関係は少なく、その大部分を並列に実行することが可能であると考える。シミュレーション上ではコアのサイクル関数を for文で逐次実行しており、#pragma omp parallel for を用いることで簡単に並列化することができる。ただし、コア部分の中でシミュレータ全体の状態を更新する部分の命令においてはその変数が共有変数として全体で共有しており、並列に実行することができない。また、ICNTへのアクセス要求はキューで管理しており、複数の SIMTコアで共有しているため、並列に実行できない。そのため#pragma omp atomicや#pragma omp criticalを用いて該当箇所を排他制御している。実際にOpenMPを用いて並列化を行った場合をソースコード 3.2、 ソースコード 3.3に示す。なお、このソースコードでは 4スレッドによる並列化である。

ソースコード 3.2: OpenMPを用いる場合 (一部抜粋、改変)1 #pragma omp parallel for num threads(4)2 for (unsigned i=0;i<simt num;i++)3 {4 m cluster[i]−>core cycle(); // 本文中のSIMTコアのサイクル関数部分を表す5 }

ソースコード 3.3: atomicを用いる場合 (一部抜粋、改変)1 SIMT::issue()2 { // SIMTコアサイクル関数内の issueステージ関数3 if( !valid inst ) // validでない命令はストールされる4 #pragma omp atomic5 // この変数はスレッド間で共有しているため、並列実行できない6 ++m stats−>shader cycle distro[0];7 }

3.2.2 SIMTコアの各パイプラインステージの高速化本節では、SIMTコア内部のパイプラインステージ関数に関する高速化手

法について述べる。3.1.2節の結果を踏まえて、issueステージ関数と executeステージ関数について検討を行う。

17

不要な状態更新の計算削減

2.2.1節で述べたように、GPGPU-Simには電力使用量を計算するGPUWattch、性能解析機能であるAerialvisionの追加機能がある。しかし、これらの機能を使用せずにシミュレーションを行う場合でも、追加機能のための状態を更新している部分がある。よってそれらの部分を削除し、不要な計算を行わないようにする。ソースコード 3.4 は不要な部分の例である。この関数は issueステージ関数にてワープが発行され実際の命令を実行する度に実行が行われるので、非常に多くの呼び出し回数があり、実行時間に大きな影響を与えている。このような関数を1つずつ削除した。

ソースコード 3.4: 必要のない状態を更新する関数例 (一部抜粋)1 void ptx thread info::ptx exec inst2 ( warp inst t &inst, const unsigned lane id)3 { /∗ 発行されたワープ内のGPUプログラム4 における実際の命令列をシミュレーションする関数 ∗/5 ptx file line stats add exec count(pI);6 }7 −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−8 void ptx file line stats add exec count(const ptx instruction ∗pInsn)9 {

10 // 命令列にひも付けされたaerialvisionのための状態更新11 ptx file line stats tracker[ptx file line(pInsn−>source file(),12 pInsn−>source line())].exec count += 1;13 }

プリフェッチ命令の追加

プリフェッチとは、計算に必要なデータを予め L1キャッシュや L2キャッシュ等にキャッシングしておき、メモリアクセスの時間を少なくすることで性能向上を図る方法である。コンパイラの最適化オプションでも、プリフェッチは行われているが、手動でプリフェッチ命令を導入することができる。

ソースコード 3.5: プリフェッチ例1 for (i = 0; i < n; i++)2 {3 a[i] = a[i] + b[i];4 builtin prefetch (&a[i+j], 1, 1); // 次の配列をプリフェッチ5 builtin prefetch (&b[i+j], 0, 1);6 }

ソースコード 3.5はGCCコンパイラのビルトイン命令を用いたプリフェッチの例である。 builtin prefetchでは3つの引数をとる。第一引数は const void*

型をとり、プリフェッチしたい値のポインタを代入する。第二引数は int型をとり、0でプリフェッチしたデータを読み込み用、1で書き込み用とする。第三引数は int型をとり、0から 3までの値をとる。3で全てのキャッシュ内にプリ

18

フェッチしたデータを残し、0でデータをキャッシュ内に残さない、1と 2は 3には劣るもののプリフェッチしたデータをキャッシュに残す。つまり、引数の数が大きいほどよりキャッシュにデータを残す。3つの引数のうち第二引数と第三引数は省略可能である。それぞれ省略した場合は第二引数は 0、第三引数は3の値となる。この例では、for文において、次にアクセスする配列のプリフェッチを行っている。ソースコード 3.6 は実際に実装した関数である。PTXにおける命令列

(ptx intruction)の計算を行う際、必要に応じてオペランドの値の読みだしや書き込みを行う必要がある。この関数は issuステージにおいて、ptx instruction

を計算する前にそのオペランドの値をプリフェッチするために使用する。PTXでは、最大で 4オペランド (dst, src1, src2, src3)を必要とする。シミュ

レーションを行う際は各オペランドは SIMTコアのレジスタ (m reg)を参照する。しかし、Fermiアーキテクチャでは約 32,000個レジスタが存在する。GPGPU-Simでは必要数のレジスタのみを確保しているが、全ての値をキャッシュに入れることはできない。そのため毎回メモリアクセスを行わなければならず、大きなレイテンシを伴うため、大きく時間を消費する。

do prefetch関数では必要となる値のアドレスをキャッシングしている。この関数をPTXの命令列を処理する前に実行しておくことによりレジスタの参照時間を短くすることができる。

ソースコード 3.6: レジスタのプリフェッチ1 void ptx thread info::do prefetch(const addr t pc)2 {3 const ptx instruction ∗pI = m func info−>get instruction(pc);4 switch(pI−>get num operands()){5 case 4:6 builtin prefetch( &( (∗m creg)[pI−>src3().get symbol()] ) ,0 ,0);7 case 3:8 builtin prefetch( &( (∗m creg)[pI−>src2().get symbol()] ) ,0 ,0);9 case 2:

10 builtin prefetch( &( (∗m creg)[pI−>src1().get symbol()] ) ,0 ,0);11 case 1:12 builtin prefetch( &( (∗m creg)[pI−>dst().get symbol()] ) ,1 ,0);13 default:14 break;15 }16 }

3.2.3 上記を含む全ての関数に対する高速化最後に、SIMTコアのサイクル関数に限らない全ての関数に対する高速化手

法について述べる。

19

assert関数の除去

assertとは C/C++における関数マクロの1つである。ソースコード 3.7にassertを用いた簡単な例を示す。

ソースコード 3.7: assert例1 x = 1;2 assert(x >= 1); // success3 assert(x < 0); // false

assert(expression) では式 expressionが偽の場合に診断メッセージを表示して関数 abort() を呼び出し、強制終了を行う。また、NDEBUGを定義すると assert()

の呼び出しは除去され、実行されない。assertは通常デバッグ用関数として用いられており、パフォーマンスを向上さ

せるためには必要がなく、ソースコードの初めに define NDEBUGを行い除去する。

try-catch文の除去

try-catch文は例外処理機能を実現する文の1つである。ソースコード 3.8にtry-catch文を用いた簡単な例を示す。

ソースコード 3.8: try-catch文例1 int input;2 cout << ”例外 0,例外 1:”;3 cin >> input; // 0と 1が入力されると例外発生4 try5 {6 if (input==0) throw 1;      // 例外を投げる(この場合は例外0)7 else if (input==1) throw ’A’;  8  // 例外を投げる(この場合は例外1)9 cout << ”例外が起きなかった” << endl;

10 }11 catch(int except){12 cout << ”int例外” << endl; // exceptが int型の時の例外13 }14 catch(char except){15 cout << ”char例外” << endl; // exceptが char型の時の例外16 }

try ブロック内では例外が発生する可能性のあるプログラムコードを書くことができる。throw文を書くと例外を発生させる。この文が実行されると try

ブロックからプログラムは即座に抜け出し実行するべき catch文を検索する。catch(type except)では typeで型を、exceptで変数名を指定する。catchブロックは、tryブロックのすぐ後に必ず記述する。

try-catch文ではその多くが catchブロック、throw文は実行時エラーの時のみ処理が行われる。そのため速度向上を図る上では必要がなく、余計な条件命令

20

の分だけ速度を低下させている。よって、最低限の try文のみを残し、他を削除した。

インライン展開

インライン展開とは、関数呼び出しのコードを呼び出し元の関数内に直接展開する機能である。この機能を使うと、スタックの確保や関数へのジャンプなどの命令実行までのオーバーヘッドを無くすことができるので、生成されるプログラムの実行速度を上げることができる。しかし、インライン展開は通常処理の少ない関数にしか適用しない。なぜならば、インライン展開はプログラムサイズを大きくするため、処理の多い関数に適用した場合、命令キャッシュを圧迫してしまう。その結果、命令を呼び出すためのメモリアクセスの回数を増加させ逆に性能低下を引き起こしてしまうためである。インライン展開は通常コンパイラにより行われているが、今回はプログラマが明示的にインライン展開を行う。ソースコード 3.9はインライン展開を用いた例である。

ソースコード 3.9: インライン関数例1 inline int func(int x)2 {3 return x + (int)(x ∗ 0.05); // 簡単な処理4 }5 int main()6 {7 func(100); // 実際には関数呼び出しは行わない8 return 0;9 }

インライン展開を行いたい関数に対して型の前に inlineと書くことにより、コンパイラにインライン展開をするように促すことができる。明示的にインライン展開を行った場合でも必ず展開されるというわけではなく、コンパイラの判断によってインライン展開されない場合もある。

21

第4章

性能評価

4.1 実行結果2.2.3節で用いたRodiniaベンチマークのサブセットに対して、それぞれ並列

化(なし、2スレッド、4スレッド、8スレッド)、プリフェッチ(あり、なし)、プリフェッチを除くその他の高速化手法(あり、なし)の3つの条件を組み合わせて評価を行った。問題サイズは表 4.1、評価環境は表 4.2 に示す。なお、実機のGPU、シミュレータ上でのモデル共にNVIDIA GeForce GTX480である。コンパイラに関してはインテルコンパイラ 15.0.3を使用した.

5回のシミュレーション結果の算術平均を表 4.3に、その速度向上率を表 4.4、図 4.1に表す。また、速度向上率の幾何平均を図 4.2に表す。なお、図および表中のdef は高速化手法なし、pf はプリフェッチのみ高速化手法を適用、opt はプリフェッチを除くすべての高速化手法を適用、opt pf はすべての高速化手法を適用した状態を表し、その後の数字はスレッド数を表している。表 4.4に示すとおり、シングルスレッドにおける高速化においては最大で

pathfinderベンチマークに対するプリフェッチを含めた全ての高速化手法を用いた時 (opt pf 1)の 1.55倍、平均ではプリフェッチを除く高速化手法を用いた時(opt 1)の 1.26倍の高速化を達成した。並列化を含めた高速化では特定のベンチマークにおいて最大、平均のどちらにおいても、プリフェッチを除く高速化手法を用いた 8スレッド実行時 (opt 8) が最も高く、pathfinderに対する 4.16倍と2.66倍の高速化を達成した。また、シングルスレッドでの高速化手法なしでは、8スレッドにした際は速度が低下していたが、シングルスレッドでの高速化手法を導入することにより、8スレッドにおいても速度向上を達成した。

22

表 4.1: アプリケーションの問題サイズアプリケーション 問題サイズ

pathfinder 40000 ×100× 20

backprop 65536

dwt2d 1024 ×1024

nw 2048 ×10

bfs 256k

hotspot 1024 ×4× 4

lud 512

srad v2 1024 ×2048× 0× 127× 0× 127× 1× 1

表 4.2: 評価環境CPU Core i7 3770K(4-core)

GPU NVIDIA GeForce GTX480

OS Ubuntu 14.04, 64bit

メモリ 16GB

CUDA 4.2

コンパイラ インテルコンパイラ 15.0.3

23

表 4.3: アプリケーションの実行時間

高速化手法 アプリケーション [s]

pathfinder backprop dwt2d nw bfs hotspot lud srad v2

def 1 382 362 433 1,034 1,217 2,228 734 1,369

def 2 268 242 304 675 767 1,499 506 925

def 4 123 137 180 580 553 766 301 557

def 8 115 179 203 897 649 762 296 546

pf 1 320 312 372 911 1052 1,871 627 1,177

pf 2 123 140 195 737 528 763 294 572

pf 4 116 136 182 722 555 1,252 294 546

pf 8 127 142 189 761 557 765 308 542

opt 1 272 270 331 799 1052 1,872 625 1,176

opt 2 163 175 221 534 524 799 296 541

opt 4 110 142 178 497 515 768 291 548

opt 8 92 130 181 445 543 773 315 538

opt pf 1 287 287 344 848 1052 1,864 627 1,176

opt pf 2 183 183 227 562 554 771 294 541

opt pf 4 148 148 176 420 525 787 295 553

opt pf 8 137 137 186 430 525 764 295 566

24

表 4.4: アプリケーションの実行時間比

高速化手法 アプリケーション 幾何平均pathfinder backprop dwt2d nw bfs hotspot lud srad v2

def 1 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00

def 2 1.43 1.49 1.46 1.53 1.59 1.49 1.45 1.48 1.49

def 4 3.31 2.65 2.47 1.78 2.20 2.91 2.44 2.46 2.47

def 8 3.31 2.02 2.19 1.15 1.87 2.93 2.48 2.51 2.21

pf 1 1.19 1.16 1.19 1.14 1.16 1.19 1.17 1.16 1.17

pf 2 3.11 2.59 2.28 1.40 2.30 2.92 2.50 2.39 2.38

pf 4 3.29 2.66 2.44 1.43 2.19 1.78 2.49 2.51 2.29

pf 8 3.12 2.55 2.35 1.36 2.19 2.91 2.38 2.52 2.36

opt 1 1.41 1.34 1.34 1.29 1.16 1.19 1.17 1.16 1.26

opt 2 2.35 2.07 2.01 1.94 2.32 2.79 2.48 2.53 2.30

opt 4 3.49 2.56 2.49 2.08 2.36 2.90 2.52 2.50 2.59

opt 8 4.16 2.79 2.45 2.32 2.24 2.88 2.33 2.55 2.66

opt pf 1 1.55 1.26 1.29 1.22 1.16 1.20 1.17 1.16 1.25

opt pf 2 2.64 1.98 1.96 1.84 2.20 2.89 2.49 2.53 2.29

opt pf 4 3.23 2.45 2.52 2.46 2.32 2.90 2.49 2.48 2.59

opt pf 8 4.01 2.64 2.38 2.41 2.32 2.92 2.49 2.42 2.65

25

図 4.1: アプリケーションの実行時間比

図 4.2: アプリケーション実行時間比の幾何平均

26

4.2 実行結果に対する性能解析次に pathfinderと nwのベンチマークに対して各手法を適用した場合の性能

解析の比較を行った。ICNT/DRAM/L2キャッシュ/SIMTコアの各クロック別領域に対して並列化のみを適用した (def ) 結果を図 4.3、図 4.4に示す。また、fetch/decode/issue/read operand/execute/writebackの各ステージに対してシングルスレッドの高速化手法のみを適用した時の結果を図 4.5、図 4.6に示す。なお、スレッド数に関するデータには同期のオーバーヘッドを含む。図 4.3、図 4.4より、並列化を行うことで、8スレッドの場合を除き SIMTコ

ア領域の実行時間の削減に成功しているということが分かる。また、図 4.5、図 4.6より、シングルスレッドのみの高速化では issueステージ、executeステージの両ステージで実行時間の削減に最大で約 15%ほど成功していることが分かる。

図 4.3: pathfinderにおける各クロック別領域の実行時間

27

図 4.4: nwにおける各クロック別領域の実行時間

図 4.5: pathfinderにおける各パイプラインステージの実行時間

28

図 4.6: nwにおける各パイプラインステージの実行時間

29

第5章

考察

5.1 シングルスレッドにおける高速化手法表 4.3と図 4.1をアプリケーション項目別に確認すると、pathfinderが最も高

い速度向上を示している。プリフェッチ命令についても、dwt2d, nwではほとんど速度向上が得られなかったのに対し、pathfinderについてはシングルスレッドでも約 10%の速度向上を示した。これはアプリケーションの IPCの大きさによるものと考えられる。GPGPU-Simを用いて各アプリケーション実行した際に得られる統計情報を表 5.1に示す。本論文においてシミュレーション精度を下げていないため、高速化手法を適用した場合でもこれらの情報には変化はない。プリフェッチ命令は issueステージ関数内のPTXの命令列を実行する前に行

われる。そのため、実行命令数が多いアプリケーションのほうがより速度向上を得られる。また、ストールが起こる場合、issue関数内でPTXの命令列が処理されず、プリフェッチ命令を用いた関数も実行されないため、速度向上が得られない。

dwt2dと nwのベンチマークにおいては総命令数は pathfinderと同程度の命令数を実行しているが、総ストール数が多いためそれほど速度向上を得られなかった。また、backpropのベンチマークにおいては、総ストール数は少ないが実行する総命令数が少ないため、速度向上がそれほど得られなかったと考えられる。

表 5.1: アプリケーションの統計情報アプリケーション 総命令数 総サイクル数 IPC 総ストール数

pathfinder 260,233,648 362,793 717 95,842

backprop 190,054,784 335,767 566 1,885,176

dwt2d 204,918,584 1,181,722 173 2,555,656

nw 207,696,896 5,268,656 39 11,400,655

30

5.2 並列性図 4.3、図 4.4のいずれからも、並列化においてはスレッド数を倍にしても、

目的とした領域の時間を半分にすることは実現できていない。スレッド数を倍にしても目的した半分にならない理由としては同期のオー

バーヘッドが考えられる。本論文の手法では、サイクル関数の実行が終了するごとに各スレッドが同期をとるため同期回数が非常に多い。そのため、同期によるオーバーヘッドが大きくなりスレッド数を倍にしても 2倍の速度向上を得ることができなかったと考えられる。また図 4.2から、1スレッドから 4スレッドまではスレッド数を増やすにつれ

て徐々に高速化することができているのに対し、4スレッドから 8スレッドではほとんど速度向上していないことが分かる。これらの原因としては評価環境が影響していると考えられる。評価環境の

CPUは 4コア 8スレッドのCPUであるため、8スレッドまで並列化することができた。4スレッドまでは物理コアの並列化であるが、8スレッド実行時はハイパースレッディング [8] による並列化が行われる。ハイパースレッディングとは、1つの物理コアに対して複数のスレッド(こ

の場合は2スレッド)を実行する技術である。ハイパースレッディング技術を用いた並列化ではその性能向上率は性能向上は約 25%程度ほどしか得られないと言われている [9] ため、理想的に高速化できたとしても 4スレッドまでと同程度の高速化を得ることは難しい。また、スレッド数を増加させるとスレッド間でのリソースの共有率は大きく

なる。8スレッドにおいては、L1, L2キャッシュは 2スレッドごと、L3キャッシュは 8スレッド全てで共有することになる。この結果、キャッシュミスの割合が増加する。キャッシュミスが起こるとメモリアクセスを行わなければならなくなり、大きなレイテンシが発生する。その結果、高速化手法を用いても、8スレッドになった場合は速度向上につながらなかったと考えられる。

5.3 関連研究本論文ではGPGPUシミュレータを高速化する手法の1つとして並列化を利

用した。この並列化手法はシミュレーション上のサイクル関数ごとに並列化する手法であった。しかし、この手法では、実行結果が変わらず、精度を落とすことがないという長所がある一方でオーバーヘッドが大きくなりコア数に比例した高速化を行うことができないという欠点がある。精度を少し下げる代わりに同期回数を減らし、GPGPU-Simの高速化を行う

研究として、[10]がある。[10]では SlackSim[11]の考えをGPGPU-Simにおいて適用している。

31

図 5.1: SlackSimのスキーム [11]

(a)cycle-by-cycle, (b)quantum-based, (c)bounded slack, (d)unbounded slack

SlackSimでは、並列化を行う際の様々な手法について検証している。図 5.1

は論文中で述べられている4つの手法である。図中の 1から 6までの数字はそのシミュレーションサイクルを表し、縦線は各スレッドが同期するタイミングを表す。図 5.1の (a)cycle-by-cycleでは、各スレッドのいずれかのサイクルが終了するたびに同期を取っている。図 5.1の (b)quantum-basedでは、同期するサイクル数を定め、そのサイクル数ごとに同期を行い、そのサイクル数までは各スレッドは連続実行を行うことができる。しかし、(a)と (b)のスキームでは先にその周期に到達したスレッドは同期を行うまで何も実行しないため、効率が悪い。図 5.1の (c)bounded slackでは、最もサイクル実行時間の長いスレッドが実行を終了するたびに同期を取るが、その他のスレッドはそのスレッドの完了

32

図 5.2: (a) cycle-by-cycleを用いた並列化、(b) Work-groupを用いた並列化 [10]

を待たずに次のサイクルの計算を実行するというものである。これにより、各スレッドの効率が上がる。図 5.1の (d)unbounded slackでは、(c)の理想形であり、同期は最後の1回のみ行う。

SlackSimでは (c)と (d)のスキームを用いてシミュレーションを行っている。本論文では、(a)のスキームを用いている。

[10]では SlackSimにおける (c)を参考にし、GPGPU-Simのプログラムの並列化を行っている。図 5.2はそれぞれ、サイクルごとの並列化、提案手法の並列化を行った場合のシミュレーションの流れである。この手法では、スレッドをSIMTスレッド、Innterconnect-Memory Subsystem(IMS)スレッド、Work

Disribution and Control(WDC)スレッド、の 3種類に分けている。SIMTスレッドは SIMTコアの動作を行うスレッド、IMSスレッドはDRAM, ICNT, L2キャッシュの動作をまとめたスレッドである。WDCスレッドは SIMTスレッドの管理を行うスレッドとなっている。

IMSスレッドとWDCスレッドは 1スレッドずつ SIMTスレッドは複数スレッド立てている。この手法では、シミュレーションを行う際、SIMTスレッドと

33

IMSスレッドにおいてある一定の動作ごとのまとまり(Work-group)を生成し実行する。そして、毎サイクル同期をするのではなく、いずれかのスレッドがWork-groupが終了する時にスレッド間の同期を行っている。これにより、並列化による同期の回数の削減を実現している。

[10]では、使用しているGPUの構成やベンチマークは異なるが本来のシミュレーションとの誤差は数%程度でありながら、平均 3.39倍の高速化を達成している

34

第6章

結論

6.1 まとめGPGPUの需要が今後もますます増加していくと考える中で、GPGPUシミュ

レータは実機に対して数千倍から数万倍の実行速度の差があり、その問題解消は解決すべき課題である。本論文では、GPGPUソフトウェアの1つであるGPGPU-Simの概要と実機との性能差について評価を行い、並列化を含む様々な高速化手法について検討を行った。シングルスレッドの高速化手法としてはプリフェッチ命令の導入、不要な状態更新を行う関数の削減、assert関数の除去、try-catch文の除去、インライン展開を用いた。並列化に関してはOpenMP

を用いた。評価はプリフェッチ命令とその他の最適化手法、並列化の有無に対してそれ

ぞれ行い、シングルスレッドの高速化においては最大で 1.55倍、平均で 1.26

倍、並列化を含めた高速化では最大で 3.47倍、平均で 2.46倍の高速化を達成できることを明らかにした。

6.2 今後の課題今後の課題としては、

• 命令がストールされる割合の高いベンチマークに対する高速化

• 個別の高速化手法に対する速度向上率の比較

• Xeon PhiやGPUなどのメニーコアプロセッサを用いた高速シミュレーション

などが挙げられる。

35

謝辞

本研究を進めるにあたり、適切かつ熱心な指導をしていただいた指導教員の吉瀬謙二准教授に深く感謝いたします。また、本研究を行うに辺り、最初の道標を示してくださった眞下達先輩、小

林諒平先輩、本論文の文章の面で様々な修正をしていただいた奥村開里先輩、森悠先輩にお礼申し上げます。そして、本研究では、共にGPUの構造から高速化までアーキテクチャやシ

ミュレータ理解の部分から高速化の実装、論文の校正に渡る点まで本当に多くのアドバイスをご教授頂いた味曽野智礼先輩には筆舌に尽くし難い感謝の意を抱いております。最後に、本研究に限らず様々な面で支えていただいた吉瀬研究室の皆様、両

親に感謝申し上げます。

36

参考文献

[1] Bakhoda, A. and Yuan, G.L. and Fung, W.W.L. and Wong, H. and Aamodt,

T.M., “Analyzing CUDA workloads using a detailed GPU simulator” IEEE

International Symposium on Performance Analysis of Systems and Software,

ISPASS, USA, pp.163-174, 2009

[2] Intel Vtune Amplifie. https://software.intel.com/en-us/intel-vtune-amplifier-

xe/

[3] CUDA. https://developer.nvidia.com/cuda-zone

[4] NVIDIA Fermi Architecture. http://nvidia.com/content/pdf/fermi white papers/

p.glaskowsky nvidia’s fermi-the first complete gpu architecture.pdf/

[5] GPGPU-Sim. http://www.gpgpu-sim.org/

[6] Shuai Che and Boyer, M. and Jiayuan Meng and Tarjan, D. and Sheaffer, J.W.

and Sang-Ha Lee and Skadron, K, “Rodinia: A benchmark suite for heteroge-

neous computing” IEEE International Symposium on Workload Characteriza-

tion IISWC, USA, pp.44-54, 2009

[7] OpenMP. http://openmp.org/wp/

[8] Intel Hype-Threading Techolog. http://www.intel.com/content/www/us/en/

architecture-and-technology/hyper-threading/hyper-threading-

technology.html

[9] Performance Insights to IntelHyper-Threading Technology.

https://software.intel.com/en-us/articles/performance-insights-to-intel-hyper-

threading-technology/

[10] Sangpil Lee, Won Woo Ro, “Parallel GPU architecture simulation framework

exploiting work allocation unit parallelism“ IEEE International Symposium in

Performance Analysis of Systems and Software, USA, pp.107-117, 2013

37

[11] Chen, Jianwei and Annavaram, Murali and Dubois, Michel, “SlackSim: A Plat-

form for Parallel Simulations of CMPs on CMPs“ SIGARCH Comput. Archit.

News, USA, pp.20-29, 2009

38