【Fortran学習|豆知識】Fortranポインタによる「メモリの再解釈」:1次元配列を2次元として扱うテクニック

導入

数値計算の現場では、メモリの連続性を保つこと(キャッシュ効率の向上やMPI通信の高速化)が非常に重要です。しかし、アルゴリズムの実装段階では、行列やグリッドデータとして2次元(あるいは多次元)インデックスでアクセスしたい場面も多いはずです。今回紹介する「ポインタによるランク再マッピング」は、物理的に1次元で確保したメモリを、論理的に2次元配列として扱うための、計算コストゼロの強力な手法です。

基礎知識

Fortranにおける「ポインタ配列(Pointer Array)」は、単なるメモリのアドレスを保持するだけでなく、そのデータの形状(ランク)や境界(Bounds)を再定義する機能を持っています。通常、配列を定義するとメモリの確保と形状の決定が同時に行われますが、`=>`(ポインタ代入演算子)を用いることで、既存のメモリ領域に対して新しい「窓(ビュー)」を当てはめることができます。これにより、データのコピーを行うことなく、多次元形式でデータにアクセスすることが可能になります。

実装/解決策

この手法を用いるには、まず基底となる1次元配列を確保し、次にその配列を指し示すポインタ変数に対して、`target`属性を持つ1次元配列を、ターゲットの形状を指定して割り当てます。この際、`=>`オペレータの左辺に形状指定を記述することで、コンパイラに対して「この1次元メモリを、どのような次元構成として解釈すべきか」を伝えます。

サンプルプログラム

以下は、1次元配列を2次元ポインタで再マッピングし、行列として操作する例です。

program pointer_mapping
implicit none
! 1次元配列の実体(メモリ確保)
real(8), target, allocatable :: flat_array(:)
! 2次元ポインタ(論理的なマッピング先)
real(8), pointer :: p2d(:, 🙂 => null()

integer :: nx, ny, i, j

nx = 3
ny = 2
allocate(flat_array(nx ny))

! 1次元データを適当に初期化
flat_array = (/1.0, 2.0, 3.0, 4.0, 5.0, 6.0/)

! ポインタによるランク再マッピング
! 1次元のflat_arrayを(1:nx, 1:ny)の2次元空間として紐付ける
p2d(1:nx, 1:ny) => flat_array

! 2次元インデックスでアクセス
print , “2次元ポインタでアクセスした値:”
do j = 1, ny
do i = 1, nx
print , “p2d(“, i, “,”, j, “) = “, p2d(i, j)
end do
end do

! 後処理
deallocate(flat_array)
end program pointer_mapping

応用・注意点

この手法を利用する際、最も注意すべき点は「メモリレイアウト(記憶順序)」です。Fortranは列優先(Column-major)であるため、`p2d(nx, ny)`という形状で再マッピングする場合、メモリ上では左側のインデックス(nx)が連続して並んでいる必要があります。もし、通信などで得られたデータがC言語由来の行優先(Row-major)データである場合は、インデックスの順序を考慮して再マッピングを行わないと、意図しない値にアクセスすることになります。また、ポインタが指している実体(`flat_array`)が`deallocate`された後もポインタを参照し続けると、セグメンテーションフォールト(メモリ不正参照)を引き起こすため、管理には十分注意してください。

コメント

タイトルとURLをコピーしました