データのアライメントを考慮するべき変数には、次のものがあります:
動的に割り当てられる変数
データ構造体の構成要素
グローバルまたはローカル変数
スタックに渡されるパラメータ
最高のパフォーマンスを得るには、データを次のようにアライメントします。
あらゆるアドレスにおける 8 ビットデータをアライメントします。
アライメントされた 4 バイトワード内に入る 16 ビットデータをアライメントします。
32 ビットデータをベースアドレスが 4 の倍数になるようにアライメントします。
64 ビットデータをベースアドレスが 8 の倍数になるようにアライメントします。
80 ビットデータをベースアドレスが 16 の倍数になるようにアライメントします。
128 ビットデータをベースアドレスが 16 の倍数になるようにアライメントします。
最適な性能を得るため、データが自然にアライメントされるように注意してください。自然境界とは、データ項目のサイズの倍数であるメモリアドレスのことです。例えば、自然境界上にアライメントされた REAL(KIND=8) のデータ項目は、8 の倍数のアドレスを持ちます。配列については、すべての要素がこのようにアライメントされているときに、配列がアライメントされているといいます。
開始アドレスが自然境界上にあるデータ項目は、「自然にアライメントされている」といいます。自然境界にアライメントされていないデータは「アライメントされていないデータ」と呼びます。
インテル® Fortran コンパイラは、可能ならば各データ項目を自然にアライメントしますが、一部の Fortran 文では、データがアライメントされないことがあります。
コマンドライン・オプション -align を使うと、データを自然にアライメントすることができますが、共通ブロック、派生型、レコード構造体中のデータ項目のデータ宣言を検証し、順序を変更することを検討してください。
データ宣言の順序とサイズを慎重に指定して、データが自然にアライメントされるようにする
最初に最も大きな数値項目を指定し、次に小さな数値項目を、最後に非数値 (文字) の項目を指定する
次のような文は、アライメントされていないデータの原因となります。
共通ブロック (COMMON 文)
COMMON 文中の変数の順は、それら変数の格納の順序を決定します。共通ブロック中のデータ項目が自然にアライメントされることが確実ではない限り、使用されるデータの最大値に応じて、 -align commons オプションか -align dcommons オプションを指定してください。「アライメント・オプション」を参照してください。
派生型 (ユーザ定義) データ
派生型データの構成要素は、TYPE 文の後に宣言されます。
データに派生型データ構造体が含まれている場合、派生型データ中のデータ項目が自然にアライメントされることが確実ではない限り、-align records オプションを指定してください。
SEQUENCE 文を省略すると、-align records オプションはすべてのデータ項目を自然にアライメントします。
SEQUENCE 文を指定すると、-align records オプションは、-align sequence オプションを指定しない限り、アライメントされていないデータの発生を防ぐのに必要なパディングを追加できなくなります (データ項目はパックされます)。 SEQUENCE 文を使用する場合、データ宣言の順序を、すべてのデータ項目が自然にアライメントされるように指定する必要があります。
レコード構造体 (RECORD と STRUCTURE 文)
インテル Fortran レコード構造体には、通常、複数のデータ項目が含まれます。STRUCTURE 文中の変数の順序は、それら変数の格納の順序を決定します。RECORD 文はレコード構造体の名前を指定します。レコード構造体は、インテル Fortran 言語拡張です。
データにレコード構造体が含まれている場合、レコード構造体のデータ項目が自然にアライメントされることが確実ではない限り、-align records オプションを指定してください。
EQUIVALENCE 文
EQUIVALENCE 文は、アライメントされないデータや、自然境界にまたがるデータを生じさせることがあります。詳細は、『Intel® Fortran Language Reference』(英語) マニュアルを参照してください。
共通ブロック、派生型構造体、またはレコード構造体中にアライメントされないデータが生じるのを防ぐには、次のいずれか、または両方の手段を取ってください。
新規のプログラムや、ソースコードの宣言を簡単に変更できるプログラムでは、データ宣言の順序を慎重に計画します。例えば、COMMON 文中では、数値データが大きいものから小さいものに配置され、最後に文字データが配置されるように変数を並べます (以下の「アライメントされないデータの発生を防ぐためのデータ宣言の順序」を参照)。
ソースコードの変更が簡単に行えない既存のプログラムや、派生型またはレコード構造体を含む配列要素の場合、コマンドライン・オプションを使って、必要に応じて空白をパディングすることで数値データがアライメントされるように、コンパイラに要求することができます。
アライメントされないデータが生じるその他の原因としては、アライメントされていない実引数や、派生型構造体またはレコード構造体を含む配列などがあります。
プログラム・ユニットの外部からの実引数が自然にアライメントされていないと、アライメントされないデータ参照が発生します。インテル Fortran は、渡されたすべての引数が自然にアライメントされていると仮定します。また、コンパイル時には、プログラムの実行中に実引数を通して渡されるデータに関して何の情報も持っていません。
個々の配列要素に派生型構造体やレコード構造体が含まれる配列の場合、配列要素のサイズにより、一部の要素 (ただし先頭の要素以外) がアライメントされていない境界から始まることがあります。
SEQUENCE 文やレコード構造体がなく、派生型構造体中でデータ項目が自然にアライメントされている場合でも、配列要素のサイズにより一部の配列要素がアライメントされなくなるのを防ぐために、-align records オプションを使って必要なパディングを行わなければならないことがあります。
-align norecords を指定するか、-align records なしで -vms を指定すると、配列要素の間ではパディング・バイトが追加されません。個々の配列要素が SEQUENCE 文付きの派生型構造体を含む場合、どのような Fortran コマンド・オプションが指定されていても、配列要素はパディング・バイトなしにパックされます。この場合、一部の要素がアライメントされなくなります。
-align records オプションが有効な場合、個々の配列要素に対してコンパイラが追加するパディング・バイト数は、構造体中の最も大きなデータ項目のサイズに依存します。コンパイラは、SEQUENCE 文のない派生型構造体、またはレコード構造体中の最も大きなデータ項目の倍数として、配列要素の大きさを計算します。その後、コンパイラは適切な数のパディング・バイトを追加します。例えば、構造体が 8 バイトの浮動小数点数の後に 3 バイトの文字変数を含む場合、各要素は 5 バイトのパディングを含むことになります (16 が 8 の倍数であるため)。しかし、構造体に 4 バイトの浮動小数点数が 1 つ、4 バイト整数が 1 つ、さらに 3 バイトの文字変数が 1 つ含まれていると、各要素は 1 バイトのパディングを含むことになります (12 が 4 の倍数であるため)。
コンパイルの際に、インテル Fortran コンパイラは、できるだけ多くのデータを自然にアライメントします。アライメントされないデータが生じるような例外的な状況については、上記で説明しています。
アライメントされていないデータはランタイム性能を低下させる可能性があるので、次の対処策を取ることをお勧めします。
共通ブロック、派生型構造体、またはレコード構造体中のデータ宣言を慎重に検証して、すべてのデータ項目が自然にアライメントされることを確認します (データ宣言については、下記のサブセクションを参照)。データ宣言の格納にモジュールを使うことで、この種のデータのアライメントに一貫性を持たせることができます。
EQUIVALENCE 文を使わないようにします。使う場合は、アライメントされないデータや、自然境界にまたがるデータを生じさせないようにします。
プログラム・ユニットの外部から渡される引数が、自然にアライメントされていることを確認します。
少なくとも 1 つの派生型構造体かレコード構造体を含む配列要素のサイズを検証して、配列要素がアライメントされた境界から始まるようになっていることを確認します (前のサブセクションを参照)。
アライメントされていないデータをレポートするには、2 つの方法があります:
コンパイルの際、(すべての警告を抑制する -warn noalignments (または -W0) オプションを指定していなければ) アライメントされないことがわかっているすべてのデータ項目について、警告メッセージが発行されます。
プログラムの実行の際、アライメントされていないことが検知されたすべてのデータについて、警告メッセージが発行されます。メッセージには、アライメントされていないアドレスが含まれます。
以下のランタイム・メッセージについて考えてみます:
Unaligned access pid=24821 <a.out> va=140000154, pc=3ff80805d60, ra=1200017bc
このメッセージでは次のことを示しています。
アライメントされていないデータ (プログラム・カウンタ) へアクセスする文は、3ff80805d60 にあります。
アライメントされていないデータは、140000154 のアドレスにあります。
新規のプログラムや、ソースコードの宣言を簡単に変更できるプログラムでは、データ宣言の順序を慎重に計画し、共通ブロック、派生型構造体、レコード構造体、または EQUIVALENCE 文によって等価にされたデータ項目が自然にアライメントされるようにします。
アライメントされないデータの発生を防ぐには、次の規則を使用します。
必ず最大サイズの数値データ項目を最初に定義するようにします。
データに文字データと数値データが混在している場合、数値データを先に指定します。
アライメントされないデータの前に、適切なサイズの小さなデータ項目 (またはパディング) を追加して、それ以降のデータが自然にアライメントされるようにします。
データの宣言時、KIND パラメータを指定するなど、明示的に長さを宣言することを検討してください。例えば、INTEGER より INTEGER(KIND=4) (または INTEGER(4)) を指定します。デフォルトのサイズを使用する場合 (INTEGER、LOGICAL、COMPLEX、REAL など)、-integer_size{16|32|64} と -real_size{32|64|128} コンパイラ・オプションは、個々のフィールドのデータ宣言サイズを変更できることに注意してください。つまり、慎重に計画されたデータ宣言の順序のデータ・アライメントが変えられてしまう可能性があります。
データ宣言のガイドラインに従うことで、データを自然にアライメントさせるためのパディング・バイトを追加する -align keyword オプションの必要性を最小限に抑えることができます。-align keyword オプションが必要な場合でも、データ宣言のガイドラインに従うと、コンパイラが追加するパディング・バイト数を最小限に抑えることができます。
common 文中のデータ項目の順序は、データ項目が格納される順を決定します。x という名前の共通ブロックが次のように宣言されているとします。
logical (kind=2) flag
integer iarry_i(3)
character(len=5) name_ch
common /x/ flag, iarry_i(3), name_ch
図 1-1 に示すように、適切な Fortran コマンド・オプションを省略すると、共通ブロックには iarry_i の第 1 配列要素の先頭から、アライメントされていないデータ項目が含まれるようになります。
図 1-1 アライメントされていないデータを含む共通ブロック
|
図 1-2 に示すように、共通ブロックを使用しているプログラム・ユニットを -align commons オプションを付けてコンパイルすると、データ項目は自然にアライメントされます。
図 1-2 自然にアライメントされたデータを含む共通ブロック
|
共通ブロック x は、大きさが 32 ビット以下のデータ項目を含むため、-align commons オプションを指定するようにします。共通ブロックが 32 ビットよりも大きくなる可能性のあるデータ項目 (REAL (KIND=8) のデータなど) を含む場合、-align commons オプションを使用します。
共通ブロックデータを使用するソースファイルを簡単に変更できる場合は、COMMON 文中の数値変数をサイズの大きい順に定義して、文字変数を最後に置きます。これは、移植性を高め、パディングなしにデータ項目を自然にアライメントし、コマンドライン・オプション -align commons または -aligndcommons オプションを必要としません。
logical (kind=2) flag
integer iarry_i(3)
character(len=5) name_ch
common /x/ iarry_i(3), flag, name_ch
図 1-3 に示すように、変数をサイズの大きい順に並べ、文字データを最後に置けば、データ項目は自然にアライメントされます。
図 1-3 自然にアライメントされるように並べ替えられたデータを含む共通ブロック
|
共通ブロックデータを使用するソースファイルをすべて変更または作成するときには、宣言に一貫性を持たせるために、共通ブロックデータ宣言を 1 つのモジュールにまとめることを検討してください。互換性の理由から共通ブロックが不要な場合 (ファイルへの格納や、Fortran 77 に使用する場合) には、共通ブロックを使わずに、データ宣言をモジュールに入れることができます。
共通ブロックと同様に、派生型構造体には複数のデータ項目が含まれることがあります。
派生型構造体中のデータ項目コンポーネントは、SEQUENCE 文と Fortran オプションの使用に関連するいくつかの例外を除いて、最大 64 ビットの境界上に自然にアライメントされます。例外については、「アライメント・オプション」を参照してください。
インテル Visual Fortran は、派生型データを、次のように値の線形な並びとして格納します。
SEQUENCE 文を指定すると、最初のデータ項目は最初の格納位置に、最後のデータ項目は最後の格納位置に格納されます。個々のデータ項目は宣言された順番に格納されます。Fortran オプションはアライメントされていないデータには影響を与えないので、データを自然にアライメントするためにはデータ宣言を慎重に指定する必要があります。-align sequence オプションは、SEQUENCE 派生型のデータ項目を自然境界にアライメントします。
SEQUENCE 文を省略すると、-align norecords オプションが指定されていない限り、インテル Fortran は、データ項目の構成要素を自然にアライメントするために必要なパディング・バイトを追加します。
次に示す例は、派生型 PART_DT の配列 CATALOG_SPRING の宣言です。
module data_defs
type part_dt
integer identifier
real weight
character(len=15) description
end type part_dt
type(part_dt) catalog_spring(30)
.
.
.
end module data_defs