2

私は valgrind と cachegrind を使用してコードをプロファイリングするのは初めてで、最近これらのツールを使用して、キャッシュの使用に関して自分のコードがどのように動作しているかを確認し始めました。単純な if ステートメントを実行すると、ほぼ毎回キャッシュ ミスが発生することがわかりました。例として、Fortran プログラムで次の派生型を使用します。

type :: particle
    real(pr), dimension(3) :: r = 0.0_pr ! position
    real(pr), dimension(3) :: p = 0.0_pr ! momentum
end type particle

type :: rcell ! position cell
    integer, dimension(6) :: bpoints = 0 ! cell grid points
    integer :: np = 0 ! number of particles in cell
    type(particle), dimension(50) :: parts ! particles in cell
end type rcell

type(rcell), dimension(:), allocatable :: rbin ! position space bins
allocate(rbin(100))

この例は、位置と運動量によって記述される最大 50 個の粒子を含む位置空間内の 100 個のセルを表しています。コードは単純なパーティクル ムーバーを使用して、特定のタイム ステップでのパーティクルの位置と運動量を更新します。これを実装するには、次のようなループを使用します。

do i = 1, numcells
    if (rbin(i)%np == 0) cycle ! skip cells with no particles
    ...
end do

if ステートメントを含めることで、特定のセルに粒子がない場合にループを循環させることで、コードを高速化できると考えました。しかし、valgrind と cachegrind ツールを使用してコードのプロファイリングを行ったところ、この単純な if ステートメントではほとんどの場合キャッシュ ミスが発生することがわかりました。--auto=yes以下は、オプションを有効にして cg_annotate を使用したこの if ステートメントの結果の例です。

Ir: 21,600,000
I1mr: 0
ILmr: 0
Dr: 4,320,000
D1mr: 4,319,057
DLmr: 4,318,979
Dw: 0
D1mw: 0
DLmw: 0

これは、実行されるたびにキャッシュ ミスのように見えます。セルをループするときにコードでこれを頻繁に行いますが、これが大幅な速度低下の原因になっていると思います。これは派生型を使用した結果ですか? ここで、または一般的に派生型でキャッシュの使用率を改善する方法はありますか?

完全を期すために、gfortran 4.8.3 でコンパイルし、次のフラグを使用しています。-g -O3 -ffast-math -mcmodel=medium -fdefault-real-8

4

0 に答える 0