この構造のループがあります
参考:マクスウェルコード例
do z=1,zend
do y=1,yend
do x=1,xend
k=arr(x,y,z)
do while(k.ne.0)
ix=fooX(k)
iy=fooY(k)
iz=fooZ(k)
x1=x(ix ,iy ,iz)
x2=x(ix+1,iy ,iz)
x3=x(ix ,iy+1,iz)
x4=x(ix+1,iy+1,iz)
x5=x(ix ,iy ,iz+1)
x6=x(ix+1,iy ,iz+1)
x7=x(ix ,iy+1,iz+1)
x8=x(ix+1,iy+1,iz+1)
y1=y(ix ,iy ,iz)
y2=y(ix+1,iy ,iz)
y3=y(ix ,iy+1,iz)
y4=y(ix+1,iy+1,iz)
y5=y(ix ,iy ,iz+1)
y6=y(ix+1,iy ,iz+1)
y7=y(ix ,iy+1,iz+1)
y8=y(ix+1,iy+1,iz+1)
z1=z(ix ,iy ,iz)
z2=z(ix+1,iy ,iz)
z3=z(ix ,iy+1,iz)
z4=z(ix+1,iy+1,iz)
z5=z(ix ,iy ,iz+1)
z6=z(ix+1,iy ,iz+1)
z7=z(ix ,iy+1,iz+1)
z8=z(ix+1,iy+1,iz+1)
sumX+=x1+x2+..x8
sumY+=y1+y2+..y8
sumZ+=z1+z2+..z8
k=linkArr(k)
enddo
enddo
enddo
enddo
x1 から x8 は、直方体の 8 つの角です。このコードをベクトル化するには 3 つの課題があります。1 つは、8 つの配列要素がメモリ内で連続していないことです。2 つ目は、固有の while ループ構造と、リンクされたリスト アクセスです。3 番目に、fooX、fooY、fooZ から返される ix、iy、iz の値が連続していません。したがって、ループの各反復には、完全に異なる ix、iy、iz のセットがあります。そのため、反復間でもメモリアクセスは分散されます。私は次のアプローチを試みました: 1. 3 レベルの DO ループを次のように展開しました。
do z=1,zend
do y=1,yend
do x=1,xend
if(arr(x,y,z).NE.0) then
kArr(indx)=arr(x,y,z)
DO WHILE (kArr(indx).NE.0)
indx = indx + 1
kArr(indx)=linkArr(kArr(indx-1))
ENDDO
endif
enddo
enddo
enddo
これにより、while ループ構造が取り除かれ、kArr で 1 つの大きなループを実行できるようになり、その中で 8 つの要素がグループ化されます (私の VPU は一度に 8 セットのデータに対応できるとします)。パフォーマンスの向上にはつながりませんでした。誰かが興味を持っている場合は、これらの詳細を投稿できます。このコードを最適化する方法について提案が必要です。私が試した別のオプションは、x、y、zデータを単一の配列に結合して、x1、y1、z1も隣接するメモリ位置にあるようにすることでした。