データのアライメントについて問題となる変数には、次のものがあります。
動的に割り当てられる変数 (ALLOCATE によって動的に割り当てられるデータは、8 バイトでアライメントされます)
データ構造体のメンバー
グローバル変数またはローカル変数
スタックに渡されるパラメーター
最高レベルのパフォーマンスを得るには、データを次のようにアライメントします。
8 ビット・データ。任意のアドレスでアライメント。
アライメントされた 4 バイトワード内に入る 16 ビット・データをアライメントします。
32 ビット・データをベースアドレスが 4 の倍数になるようにアライメントします。
64 ビット・データをベースアドレスが 8 の倍数になるようにアライメントします。
128 ビット・データをベースアドレスが 16 の倍数 (8 バイト境界) になるようにアライメントします。
最適な性能を得るため、データが自然にアライメントされるように注意してください。自然境界とは、データ項目のサイズの倍数であるメモリーアドレスのことです。例えば、自然境界上にアライメントされた REAL(KIND=8) のデータ項目は、8 の倍数のアドレスを持ちます。配列については、すべての要素がこのようにアライメントされているときに、配列がアライメントされているといいます。
開始アドレスが自然境界上にあるデータ項目は、「自然にアライメントされている」といいます。自然境界にアライメントされていないデータは「アライメントされていないデータ」と呼びます。
インテル® コンパイラーは、可能ならば各データ項目を自然にアライメントしますが、一部の Fortran 文では、データがアライメントされないことがあります。
align コマンドオプションを使うと、データを自然にアライメントすることができますが、共通ブロック、派生型、レコード構造体中のデータ項目のデータ宣言を検証し、順序を変更することを検討してください。
データ宣言の順序とサイズを慎重に指定して、データが自然にアライメントされるようにする
最初に最も大きな数値項目を指定し、次に小さな数値項目を、最後に非数値 (文字) の項目を指定する
!DEC$ ATTRIBUTES ALIGN 宣言子は、変数のバイト・アライメントを指定します。
共通ブロック (COMMON 文)、派生型データ、およびレコード構造体 (RECORD 文) は、通常は大きな構造中に複数の項目が含まれています。
次のような文は、アライメントされていないデータの原因となります。
命令文 |
オプション |
説明 |
---|---|---|
共通ブロック (COMMON 文) |
commons または dcommons |
COMMON 文中の変数の順は、それら変数の格納の順序を決定します。共通ブロック中のデータ項目が自然にアライメントされることが確実ではない限り、使用されるデータの最大値に応じて、-align commons オプションか -align dcommons (Linux*)、または /align:commons あるいは /align:dcommons (Windows*) オプションを指定してください。 |
派生型 |
records または sequence |
派生型データのデータ項目は、TYPE 文の後に宣言されます。 データに派生型データ構造体が含まれている場合、派生型データ中のデータ項目が自然にアライメントされることが確実ではない限り、-align records (Linux) または /align:records (Windows*) オプションを指定してください。 SEQUENCE 文を省略すると、-align records (Linux) または /align:records (Windows*) オプションはすべてのデータ項目を自然にアライメントします。 SEQUENCE 文を指定すると、-align records (Linux) または /align:records (Windows*) オプションは、SEQUENCE を指定しない限り、アライメントされていないデータの発生を防ぐのに必要なパディングを追加できなくなります (データ項目はパックされます)。SEQUENCE 文を使用する場合、データ宣言の順序を、すべてのデータ項目が自然にアライメントされるように指定する必要があります。 |
レコード構造体 (RECORD と STRUCTURE 文) |
record |
インテル® Fortran レコード構造体には、通常、複数のデータ項目が含まれます。STRUCTURE 文中の変数の順序は、それら変数の格納の順序を決定します。RECORD 文はレコード構造体の名前を指定します。レコード構造体は、インテル® Fortran 言語拡張です。 データにレコード構造体が含まれている場合、レコード構造体のデータ項目が自然にアライメントされることが確実ではない限り、-align records (Linux) または /align:records (Windows*) オプションを指定してください。 |
EQUIVALENCE 文 |
|
EQUIVALENCE 文は、アライメントされないデータや、自然境界にまたがるデータを生じさせることがあります。詳細は、「Language Reference」(英語) マニュアルを参照してください。 |
共通ブロック、派生型データ、またはレコード構造体 (拡張) 中にアライメントされないデータが生じるのを防ぐには、次のいずれか、または両方の手段を取ってください。
新規のプログラムや、ソースコードの宣言を簡単に変更できるプログラムでは、データ宣言の順序を慎重に計画します。例えば、COMMON 文中では、数値データが大きいものから小さいものに配置され、最後に文字データが配置されるように変数を並べます (以下の「アライメントされないデータの発生を防ぐためのデータ宣言の順序」を参照)。
ソースコードの変更が簡単に行えない既存のプログラムや、派生型またはレコード構造体を含む配列要素の場合、コマンドライン・オプションを使って、必要に応じて空白をパディングすることで数値データがアライメントされるように、コンパイラーに要求することができます。
アライメントされないデータが生じるその他の原因としては、アライメントされていない実引数や、構造型構造体またはインテル® Fortran レコード構造体を含む配列などがあります。
プログラムユニットの外部からの実引数が自然にアライメントされていないと、アライメントされないデータ参照が発生します。インテル® Fortran は、渡されたすべての引数が自然にアライメントされていると仮定します。また、コンパイル時には、プログラムの実行中に実引数を通して渡されるデータに関して何の情報も持っていません。
個々の配列要素に派生型構造体やインテル® Fortran レコード構造体が含まれる配列の場合、配列要素のサイズにより、一部の要素 (ただし先頭の要素以外) がアライメントされていない境界から始まることがあります。
SEQUENCE 文やレコード構造体がなく、派生型構造体中でデータ項目が自然にアライメントされている場合でも、配列要素のサイズにより一部の配列要素がアライメントされなくなるのを防ぐために、-align records (Linux) または /align:records (Windows*) オプションを使って必要なパディングを行わなければならないことがあります。
-align norecords (Linux) または /align:norecords (Windows*) を指定するか、RECORDS なしで -vms (Linux) または /Qvms (Windows*) を指定すると、配列要素の間ではパディングバイトが追加されません。個々の配列要素が SEQUENCE 文付きの派生型構造体を含む場合、どのような Fortran コマンドオプションが指定されていても、配列要素はパディングバイトなしにパックされます。この場合、一部の要素がアライメントされなくなります。
-align records (Linux) または /align:records (Windows*) オプションが有効な場合、個々の配列要素に対してコンパイラーが追加するパディングバイト数は、構造体中の最も大きなデータ項目のサイズに依存します。コンパイラーは、SEQUENCE 文のない派生型構造体、またはレコード構造体中の最も大きなデータ項目の倍数として、配列要素の大きさを計算します。その後、コンパイラーは適切な数のパディングバイトを追加します。例えば、構造体が 8 バイトの浮動小数点数の後に 3 バイトの文字変数を含む場合、各要素は 5 バイトのパディングを含むことになります (16 が 8 の倍数であるため)。しかし、構造体に 4 バイトの浮動小数点数が 1 つ、4 バイト整数が 1 つ、さらに 3 バイトの文字変数が 1 つ含まれていると、各要素は 1 バイトのパディングを含むことになります (12 が 4 の倍数であるため)。
コンパイルの際に、インテル® コンパイラーは、できるだけ多くのデータを自然にアライメントします。アライメントされないデータが生じるような例外的な状況については、上記で説明しています。
アライメントされていないデータはランタイム性能を低下させる可能性があるので、次の対処策を取ることをお勧めします。
共通ブロック、派生型データ、またはレコード構造体中のデータ宣言を慎重に検証して、すべてのデータ項目が自然にアライメントされることを確認します (データ宣言については、下記のサブセクションを参照)。データ宣言の格納にモジュールを使うことで、この種のデータのアライメントに一貫性を持たせることができます。
EQUIVALENCE 文を使わないようにします。使う場合は、アライメントされないデータや、自然境界にまたがるデータを生じさせないようにします。
プログラムユニットの外部から渡される引数が、自然にアライメントされていることを確認します。
少なくとも 1 つの派生型データかレコード構造体 (拡張) を含む配列要素のサイズを検証して、配列要素がアライメントされた境界から始まるようになっていることを確認します (前のサブセクションを参照)。
アライメントされていないデータをレポートするには、2 つの方法があります。
コンパイルの際、(すべての警告を抑制する -warn noalignments (または -warn none) (Linux) または /warn:noalignments (または /warn:none) (Windows*) オプションを指定していなければ) アライメントされないことがわかっているすべてのデータ項目について、警告メッセージが発行されます。
プログラムの実行の際、アライメントされていないことが検知されたすべてのデータについて、警告メッセージが発行されます。メッセージには、アライメントされていないアドレスが含まれます。
以下のランタイムメッセージについて考えてみます。
例 |
---|
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 など) を使用する場合、次のコンパイラー・オプションは、個々のフィールドのデータ宣言サイズを変更できることに注意してください。つまり、慎重に計画されたデータ宣言の順序によるデータ・アライメントが変えられてしまう可能性があります。
オペレーティング・システム |
コンパイラー・オプション |
---|---|
Windows* |
/4I または /4R |
Linux* および Mac OS* X |
-integer_size または -real_size |
データ宣言のガイドラインに従うことで、データを自然にアライメントさせるためにパディングバイトを追加する -align keyword (Linux) または /align:keyword (Windows*) オプションの必要性を最小限に抑えることができます。-align keyword (Linux) または /align:keyword (Windows*) オプションが必要な場合でも、データ宣言のガイドラインに従うと、コンパイラーが追加するパディングバイト数を最小限に抑えることができます。
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-2 に示すように、共通ブロックを使用しているプログラムユニットを -align commons (Linux) または /align:commons (Windows*) オプションを付けてコンパイルすると、データ項目は自然にアライメントされます。
共通ブロック x は、大きさが 32 ビット以下のデータ項目を含むため、-align commons (Linux)、/align:commons (Windows*) オプションを指定するようにします。共通ブロックが 32 ビットよりも大きくなる可能性のあるデータ項目 (REAL (KIND=8) のデータなど) を含む場合、-align commons (Linux)、/align:commons (Windows*) オプションを使用します。
共通ブロックデータを使用するソースファイルを簡単に変更できる場合は、COMMON 文中の数値変数をサイズの大きい順に定義して、文字変数を最後に置きます。これは、移植性を高め、パディングなしにデータ項目を自然にアライメントし、Fortran コマンドオプション -align commons (Linux)、-align dcommons (Windows*)、または -align commons (Linux)、/align:commons (Windows*) オプションを必要としません。
例 |
---|
LOGICAL (KIND=2) FLAG INTEGER IARRY_I(3) CHARACTER(LEN=5) NAME_CH COMMON /X/ IARRY_I(3), FLAG, NAME_CH |
図 1-3 に示すように、変数をサイズの大きい順に並べ、文字データを最後に置けば、データ項目は自然にアライメントされます。
共通ブロックデータを使用するソースファイルをすべて変更または作成するときには、宣言に一貫性を持たせるために、共通ブロックデータ宣言を 1 つのモジュールにまとめることを検討してください。互換性の理由から共通ブロックが不要な場合 (ファイルへの格納や、Fortran 77 に使用する場合) には、共通ブロックを使わずに、データ宣言をモジュールに入れることができます。
共通ブロックと同様に、派生型データには複数のデータ項目が含まれることがあります。
派生型データ中のデータ項目コンポーネントは、SEQUENCE 文と Fortran オプションの使用に関連するいくつかの例外を除いて、最大 64 ビットの境界上に自然にアライメントされます。
インテル® Visual Fortran は、派生型データを、次のように値の線形な並びとして格納します。
SEQUENCE 文を指定すると、最初のデータ項目は最初の格納位置に、最後のデータ項目は最後の格納位置に格納されます。個々のデータ項目は宣言された順番に格納されます。Fortran オプションはアライメントされていないデータには影響を与えないので、データを自然にアライメントするためにはデータ宣言を慎重に指定する必要があります。-align sequence (Linux)、/align:sequence (Windows*) オプションは、SEQUENCE 派生型のデータ項目を自然境界にアライメントします。
SEQUENCE 文を省略すると、-align norecords (Linux)、/align:norecords (Windows*) オプションが指定されていない限り、インテル® 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 |
図 1-4 に示すように、最も大きな数値データ項目が最初に定義され、文字型データが最後に定義されています。データ項目間にパディング文字はなく、すべての項目が自然にアライメントされています。末尾のパディングバイトが必要なのは、CATALOG_SPRING が配列のためです。これは、-align records (Linux)、/align:records (Windows*) オプションが有効な場合、コンパイラーによって挿入されます。
インテル® Fortran は、インテル® Fortran が提供するレコード構造体をサポートします。インテル® Fortran レコード構造体は RECORD 文と、オプションとして STRUCTURE 文を使用します。これらは、FORTRAN-77 と Fortran 標準の拡張です。STRUCTURE 文中のデータ項目の順序は、データ項目が格納される順を決定します。
インテル® Fortran は、レコードをメモリー内に値の線形な並びとして格納します。レコードの第 1 要素が第 1 格納位置に、最後の要素が最後の格納位置に格納されます。-align norecords (Linux)、/align:norecords (Windows*) を指定しない限り、データフィールドが自然にアライメントされるように、必要に応じてパディングバイトが追加されます。
次の例は、構造体の宣言、RECORD 文、および結果として得られるレコードがメモリーに格納される様子を示しています。
例 |
---|
STRUCTURE /STRA/ CHARACTER*1 CHR INTEGER*4 INT END STRUCTURE ... RECORD /STRA/ REC |
図 1-5 は、レコード REC が自然なアライメントのレコードとして格納されている様子を示すメモリーです。
© 1996-2010 Intel Corporation. 無断での引用、転載を禁じます。