gfortranでの暗黙のdoを使用した配列コンストラクターの奇妙な初期化動作

カコ

3つの倍精度配列があるとしましょう。

real*8, dimension(n) :: x, y, z

として初期化されます

x = 1.
y = (/ (1., i=1,n) /)
z = (/ (1. +0*i, i=1,n) /)

すべての配列のすべての要素をに初期化する必要があります1ifort(16.0.0 20150815)、これは、いずれかの意図したとおりに動作n宣言された精度の範囲内です。つまり、次のように初期化するn

integer*4, parameter :: n

である限りn < 2147483647、初期化はすべての宣言で意図したとおりに機能します。

gfortran(4.8.5 20150623レッドハット4.8.5-16)、初期化が失敗したためy、長いほど(一定の引数を持つ配列内包)n>65535独立その精度。AFAIK65535は、の最大値でありunsigned short int、別名unsigned int*2、の範囲内にありますinteger*4

以下はMWEです。

program test
    implicit none

    integer*4, parameter :: n = 65536
    integer*4, parameter :: m = 65535
    real*8, dimension(n) :: x, y, z
    real*8, dimension(m) :: a, b, c
    integer*4 :: i

    print *, huge(n)

    x = 1.
    y = (/ (1., i=1,n) /)
    z = (/ (1.+0*i, i=1,n) /)
    print *, x(n), y(n), z(n)

    a = 1.
    b = (/ (1., i=1,m) /)
    c = (/ (1.+0*i, i=1,m) /)
    print *, a(m), c(m), c(m)
end program test

gfortrangfortran test.f90 -o gfortran_test)でコンパイルすると、次のように出力されます。

  2147483647
   1.0000000000000000        0.0000000000000000        1.0000000000000000     
   1.0000000000000000        1.0000000000000000        1.0000000000000000

ifortifort test.f90 -o ifort_test)でコンパイルすると、次のように出力されます。

2147483647
   1.00000000000000        1.00000000000000        1.00000000000000     
   1.00000000000000        1.00000000000000        1.00000000000000     

何が得られますか?

ウラジミールF

コンパイラが配列コンストラクタを処理する方法には、確かに大きな違いがあります。n<=65535オブジェクトファイル(またはいくつかの中間表現)に格納されている[1.、1.、1。、...]の実際の配列があるためです。

より大きな配列の場合、コンパイラはループを生成します。

    (*(real(kind=8)[65536] * restrict) atmp.0.data)[offset.1] = 1.0e+0;
    offset.1 = offset.1 + 1;
    {
      integer(kind=8) S.2;

      S.2 = 0;
      while (1)
        {
          if (S.2 > 65535) goto L.1;
          y[S.2] = (*(real(kind=8)[65536] * restrict) atmp.0.data)[S.2];
          S.2 = S.2 + 1;
        }
      L.1:;
    }

私には、最初に一時配列の1つの要素のみを設定し、次に(ほとんど未定義の)一時配列をにコピーするように見えますyそしてそれは間違っています。Valgrindは、初期化されていないメモリの使用状況も報告します。

デフォルトの実数については、

    while (1)
      {
        if (shadow_loopvar.2 > 65536) goto L.1;
        (*(real(kind=4)[65536] * restrict) atmp.0.data)[offset.1] = 1.0e+0;
        offset.1 = offset.1 + 1;
        shadow_loopvar.2 = shadow_loopvar.2 + 1;
      }
    L.1:;
    {
      integer(kind=8) S.3;

      S.3 = 0;
      while (1)
        {
          if (S.3 > 65535) goto L.2;
          y[S.3] = (*(real(kind=4)[65536] * restrict) atmp.0.data)[S.3];
          S.3 = S.3 + 1;
        }
      L.2:;
    }

これで2つのループができました。1つは一時配列全体を設定し、もう1つはそれをコピーしてyすべてが正常です。

結論:コンパイラのバグ。

この問題は、この質問を読んだGCC開発者によって修正されました。バグはhttps://gcc.gnu.org/bugzilla/show_bug.cgi?id=84931で追跡されています

彼らはまた、問題が型変換に関連していることを確認しました。コンストラクターにはデフォルトの精度が1.あり、単精度配列では型変換はありませんが、倍精度配列の場合は型変換があります。それがこれら2つのケースの違いを引き起こしました。

この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。

侵害の場合は、連絡してください[email protected]

編集
0

コメントを追加

0

関連記事

分類Dev

構造体の初期化での暗黙的なコピーコンストラクターのエラー

分類Dev

MSVCでの配列の初期化中に、コピーまたは移動コンストラクタなしで呼び出されたデストラクタ

分類Dev

テンプレート化されたクラス配列の引数推定による暗黙の初期化

分類Dev

型クラスとパッケージオブジェクトを使用した奇妙な暗黙の解決動作

分類Dev

配列コンストラクターで繰り返しスカラー値を構築する暗黙のdo

分類Dev

GLSL:関数パラメーターを使用した暗黙的なサイズの配列へのアクセス

分類Dev

C ++ 11スタイルでオブジェクトの配列を初期化しようとしているときに、コンパイラがコンストラクタを暗黙的に削除する理由

分類Dev

配列を使用したコロン演算子の奇妙な動作

分類Dev

メソッド/コンストラクター引数を介した暗黙的な使用と暗黙的な使用

分類Dev

動的に割り当てられたchar配列は、コンストラクターで初期化されていないものとして表示されます

分類Dev

配列とコンストラクターの初期化が機能しない

分類Dev

文字列データの派手な配列を初期化する奇妙な動作

分類Dev

コンストラクターでのC ++の不要な暗黙的な変換

分類Dev

コンストラクターをチェーンするとき、JVMの暗黙のメモリバリアはどのように動作しますか?

分類Dev

コピーコンストラクターを削除した場合、暗黙の移動コンストラクターは取得されませんか?

分類Dev

奇妙なコンストラクターの動作

分類Dev

コンストラクタ初期化リストでstd :: vectorの配列を初期化しています

分類Dev

C ++コンストラクターの暗黙的な型変換

分類Dev

const参照を返す暗黙の変換演算子を使用したクラスでのstatic_cast <>の動作

分類Dev

Angularjs1.6.1で複数のトランスクルージョンコンポーネントを使用した奇妙な動作

分類Dev

暗黙的にインスタンス化された変数テンプレートの動的初期化の順序

分類Dev

リストとマップの「ルックアップ」を使用したScalaの暗黙的な値の動作

分類Dev

宣言された引数転送コンストラクターを使用した構造体の暗黙的なコピー

分類Dev

初期化子リストから(暗黙のコンストラクターを介して)ベクトルを開始するときに、move構文が使用されないのはなぜですか

分類Dev

C ++でコンストラクター(コンストラクターのみ)を使用して、クラス内の大きなプライベート配列を初期化する方法は?

分類Dev

コンストラクターを使用して、定義された構造体へのポインターの配列を初期化する

分類Dev

この場合、コンストラクターまたは明示的な関数を介したより良い暗黙の変換は何ですか?

分類Dev

Javaコンストラクターでフィールドの簡略配列初期化を使用できないのはなぜですか?

分類Dev

トランスポート層としてTCPを使用したZeroMQPUB / SUBパターンの奇妙な動作

Related 関連記事

  1. 1

    構造体の初期化での暗黙的なコピーコンストラクターのエラー

  2. 2

    MSVCでの配列の初期化中に、コピーまたは移動コンストラクタなしで呼び出されたデストラクタ

  3. 3

    テンプレート化されたクラス配列の引数推定による暗黙の初期化

  4. 4

    型クラスとパッケージオブジェクトを使用した奇妙な暗黙の解決動作

  5. 5

    配列コンストラクターで繰り返しスカラー値を構築する暗黙のdo

  6. 6

    GLSL:関数パラメーターを使用した暗黙的なサイズの配列へのアクセス

  7. 7

    C ++ 11スタイルでオブジェクトの配列を初期化しようとしているときに、コンパイラがコンストラクタを暗黙的に削除する理由

  8. 8

    配列を使用したコロン演算子の奇妙な動作

  9. 9

    メソッド/コンストラクター引数を介した暗黙的な使用と暗黙的な使用

  10. 10

    動的に割り当てられたchar配列は、コンストラクターで初期化されていないものとして表示されます

  11. 11

    配列とコンストラクターの初期化が機能しない

  12. 12

    文字列データの派手な配列を初期化する奇妙な動作

  13. 13

    コンストラクターでのC ++の不要な暗黙的な変換

  14. 14

    コンストラクターをチェーンするとき、JVMの暗黙のメモリバリアはどのように動作しますか?

  15. 15

    コピーコンストラクターを削除した場合、暗黙の移動コンストラクターは取得されませんか?

  16. 16

    奇妙なコンストラクターの動作

  17. 17

    コンストラクタ初期化リストでstd :: vectorの配列を初期化しています

  18. 18

    C ++コンストラクターの暗黙的な型変換

  19. 19

    const参照を返す暗黙の変換演算子を使用したクラスでのstatic_cast <>の動作

  20. 20

    Angularjs1.6.1で複数のトランスクルージョンコンポーネントを使用した奇妙な動作

  21. 21

    暗黙的にインスタンス化された変数テンプレートの動的初期化の順序

  22. 22

    リストとマップの「ルックアップ」を使用したScalaの暗黙的な値の動作

  23. 23

    宣言された引数転送コンストラクターを使用した構造体の暗黙的なコピー

  24. 24

    初期化子リストから(暗黙のコンストラクターを介して)ベクトルを開始するときに、move構文が使用されないのはなぜですか

  25. 25

    C ++でコンストラクター(コンストラクターのみ)を使用して、クラス内の大きなプライベート配列を初期化する方法は?

  26. 26

    コンストラクターを使用して、定義された構造体へのポインターの配列を初期化する

  27. 27

    この場合、コンストラクターまたは明示的な関数を介したより良い暗黙の変換は何ですか?

  28. 28

    Javaコンストラクターでフィールドの簡略配列初期化を使用できないのはなぜですか?

  29. 29

    トランスポート層としてTCPを使用したZeroMQPUB / SUBパターンの奇妙な動作

ホットタグ

アーカイブ