2 GBを超えるコードでのGCCコンパイルエラー


108

私は合計で約2.8 GBのオブジェクトコードの膨大な数の関数を持っています(残念ながら、回避策はありません。科学計算...)

それらをリンクしようとすると、(予期される)relocation truncated to fit: R_X86_64_32Sエラーが発生し-mcmodel=mediumます。コンパイラフラグを指定することで回避したいと考えました。私が制御していることに加えてリンクされているすべてのライブラリは、-fpicフラグを使用してコンパイルされています。

それでもエラーは解決せず、リンク先のライブラリの一部がPICでコンパイルされていないと思います。

ここにエラーがあります:

/usr/lib/gcc/x86_64-redhat-linux/4.1.2/../../../../lib64/crt1.o: In function `_start':
(.text+0x12): relocation truncated to fit: R_X86_64_32S against symbol `__libc_csu_fini'     defined in .text section in /usr/lib64/libc_nonshared.a(elf-init.oS)
/usr/lib/gcc/x86_64-redhat-linux/4.1.2/../../../../lib64/crt1.o: In function `_start':
(.text+0x19): relocation truncated to fit: R_X86_64_32S against symbol `__libc_csu_init'    defined in .text section in /usr/lib64/libc_nonshared.a(elf-init.oS)
/usr/lib/gcc/x86_64-redhat-linux/4.1.2/../../../../lib64/crt1.o: In function `_start':
(.text+0x20): undefined reference to `main'
/usr/lib/gcc/x86_64-redhat-linux/4.1.2/../../../../lib64/crti.o: In function    `call_gmon_start':
(.text+0x7): relocation truncated to fit: R_X86_64_GOTPCREL against undefined symbol      `__gmon_start__'
/usr/lib/gcc/x86_64-redhat-linux/4.1.2/crtbegin.o: In function `__do_global_dtors_aux':
crtstuff.c:(.text+0xb): relocation truncated to fit: R_X86_64_PC32 against `.bss' 
crtstuff.c:(.text+0x13): relocation truncated to fit: R_X86_64_32 against symbol `__DTOR_END__' defined in .dtors section in /usr/lib/gcc/x86_64-redhat-linux/4.1.2/crtend.o
crtstuff.c:(.text+0x19): relocation truncated to fit: R_X86_64_32S against `.dtors'
crtstuff.c:(.text+0x28): relocation truncated to fit: R_X86_64_PC32 against `.bss'
crtstuff.c:(.text+0x38): relocation truncated to fit: R_X86_64_PC32 against `.bss'
crtstuff.c:(.text+0x3f): relocation truncated to fit: R_X86_64_32S against `.dtors'
crtstuff.c:(.text+0x46): relocation truncated to fit: R_X86_64_PC32 against `.bss'
crtstuff.c:(.text+0x51): additional relocation overflows omitted from the output
collect2: ld returned 1 exit status
make: *** [testsme] Error 1

そして私がリンクするシステムライブラリ:

-lgfortran -lm -lrt -lpthread

問題を探す手がかりはありますか?

編集:まず最初に、ディスカッションをありがとう...少し明確にするために、私は次のような数百の関数(それぞれ個別のオブジェクトファイルでサイズが約1 MB)を持っています。

double func1(std::tr1::unordered_map<int, double> & csc, 
             std::vector<EvaluationNode::Ptr> & ti, 
             ProcessVars & s)
{
    double sum, prefactor, expr;

    prefactor = +s.ds8*s.ds10*ti[0]->value();
    expr =       ( - 5/243.*(s.x14*s.x15*csc[49300] + 9/10.*s.x14*s.x15*csc[49301] +
           1/10.*s.x14*s.x15*csc[49302] - 3/5.*s.x14*s.x15*csc[49303] -
           27/10.*s.x14*s.x15*csc[49304] + 12/5.*s.x14*s.x15*csc[49305] -
           3/10.*s.x14*s.x15*csc[49306] - 4/5.*s.x14*s.x15*csc[49307] +
           21/10.*s.x14*s.x15*csc[49308] + 1/10.*s.x14*s.x15*csc[49309] -
           s.x14*s.x15*csc[51370] - 9/10.*s.x14*s.x15*csc[51371] -
           1/10.*s.x14*s.x15*csc[51372] + 3/5.*s.x14*s.x15*csc[51373] +
           27/10.*s.x14*s.x15*csc[51374] - 12/5.*s.x14*s.x15*csc[51375] +
           3/10.*s.x14*s.x15*csc[51376] + 4/5.*s.x14*s.x15*csc[51377] -
           21/10.*s.x14*s.x15*csc[51378] - 1/10.*s.x14*s.x15*csc[51379] -
           2*s.x14*s.x15*csc[55100] - 9/5.*s.x14*s.x15*csc[55101] -
           1/5.*s.x14*s.x15*csc[55102] + 6/5.*s.x14*s.x15*csc[55103] +
           27/5.*s.x14*s.x15*csc[55104] - 24/5.*s.x14*s.x15*csc[55105] +
           3/5.*s.x14*s.x15*csc[55106] + 8/5.*s.x14*s.x15*csc[55107] -
           21/5.*s.x14*s.x15*csc[55108] - 1/5.*s.x14*s.x15*csc[55109] -
           2*s.x14*s.x15*csc[55170] - 9/5.*s.x14*s.x15*csc[55171] -
           1/5.*s.x14*s.x15*csc[55172] + 6/5.*s.x14*s.x15*csc[55173] +
           27/5.*s.x14*s.x15*csc[55174] - 24/5.*s.x14*s.x15*csc[55175] +
           // ...
           ;

        sum += prefactor*expr;
    // ...
    return sum;
}

オブジェクトsは比較的小さくti、外部ライブラリからdoubleを返すだけで、必要な定数x14、x15、...、ds0、...などを保持します。ご覧のとおり、csc[]は事前に計算された値のマップであり、次の形式の個別のオブジェクトファイル(これも数百のサイズでそれぞれ約1 MBです)でも評価されます。

void cscs132(std::tr1::unordered_map<int,double> & csc, ProcessVars & s)
{
    {
    double csc19295 =       + s.ds0*s.ds1*s.ds2 * ( -
           32*s.x12pow2*s.x15*s.x34*s.mbpow2*s.mWpowinv2 -
           32*s.x12pow2*s.x15*s.x35*s.mbpow2*s.mWpowinv2 -
           32*s.x12pow2*s.x15*s.x35*s.x45*s.mWpowinv2 -
           32*s.x12pow2*s.x25*s.x34*s.mbpow2*s.mWpowinv2 -
           32*s.x12pow2*s.x25*s.x35*s.mbpow2*s.mWpowinv2 -
           32*s.x12pow2*s.x25*s.x35*s.x45*s.mWpowinv2 +
           32*s.x12pow2*s.x34*s.mbpow4*s.mWpowinv2 +
           32*s.x12pow2*s.x34*s.x35*s.mbpow2*s.mWpowinv2 +
           32*s.x12pow2*s.x34*s.x45*s.mbpow2*s.mWpowinv2 +
           32*s.x12pow2*s.x35*s.mbpow4*s.mWpowinv2 +
           32*s.x12pow2*s.x35pow2*s.mbpow2*s.mWpowinv2 +
           32*s.x12pow2*s.x35pow2*s.x45*s.mWpowinv2 +
           64*s.x12pow2*s.x35*s.x45*s.mbpow2*s.mWpowinv2 +
           32*s.x12pow2*s.x35*s.x45pow2*s.mWpowinv2 -
           64*s.x12*s.p1p3*s.x15*s.mbpow4*s.mWpowinv2 +
           64*s.x12*s.p1p3*s.x15pow2*s.mbpow2*s.mWpowinv2 +
           96*s.x12*s.p1p3*s.x15*s.x25*s.mbpow2*s.mWpowinv2 -
           64*s.x12*s.p1p3*s.x15*s.x35*s.mbpow2*s.mWpowinv2 -
           64*s.x12*s.p1p3*s.x15*s.x45*s.mbpow2*s.mWpowinv2 -
           32*s.x12*s.p1p3*s.x25*s.mbpow4*s.mWpowinv2 +
           32*s.x12*s.p1p3*s.x25pow2*s.mbpow2*s.mWpowinv2 -
           32*s.x12*s.p1p3*s.x25*s.x35*s.mbpow2*s.mWpowinv2 -
           32*s.x12*s.p1p3*s.x25*s.x45*s.mbpow2*s.mWpowinv2 -
           32*s.x12*s.p1p3*s.x45*s.mbpow2 +
           64*s.x12*s.x14*s.x15pow2*s.x35*s.mWpowinv2 +
           96*s.x12*s.x14*s.x15*s.x25*s.x35*s.mWpowinv2 +
           32*s.x12*s.x14*s.x15*s.x34*s.mbpow2*s.mWpowinv2 -
           32*s.x12*s.x14*s.x15*s.x35*s.mbpow2*s.mWpowinv2 -
           64*s.x12*s.x14*s.x15*s.x35pow2*s.mWpowinv2 -
           32*s.x12*s.x14*s.x15*s.x35*s.x45*s.mWpowinv2 +
           32*s.x12*s.x14*s.x25pow2*s.x35*s.mWpowinv2 +
           32*s.x12*s.x14*s.x25*s.x34*s.mbpow2*s.mWpowinv2 -
           32*s.x12*s.x14*s.x25*s.x35pow2*s.mWpowinv2 -
           // ...

       csc.insert(cscMap::value_type(192953, csc19295));
    }

    {
       double csc19296 =      // ... ;

       csc.insert(cscMap::value_type(192956, csc19296));
    }

    // ...
}

それだけです。最後のステップは、それらすべてを呼び出しfunc[i]て結果を合計することです。

これはかなり特殊で珍しいケースであるという事実に関して:はい、そうです。これは、素粒子物理学の高精度計算を行おうとするときに人々が対処しなければならないことです。

EDIT2:x12、x13などは実際には定数ではないことも追加する必要があります。それらは特定の値に設定され、それらすべての関数が実行されて結果が返され、次にx12、x13などの新しいセットが選択されて次の値が生成されます。そして、これは10 ^ 5から10 ^ 6回行われなければなりません...

EDIT3:これまでの提案とディスカッションに感謝します...ループをコード生成時にロールアップしようと思いますが、これを正確に行う方法はわかりませんが、これが最善の策です。

ところで、私は「これは科学計算です-最適化する方法はありません」の背後に隠れようとはしませんでした。このコードの基礎は、私が実際にアクセスできない「ブラックボックス」から出てくるものであり、さらに、すべてが単純な例でうまく機能し、主に実際に発生することに圧倒されていると感じているだけです。世界のアプリケーション...

EDIT4:したがって、cscコンピュータ代数システム(Mathematica)の式を簡略化することで、定義のコードサイズを約1分の1 に減らすことができました。私はまた、コードを生成する前に他のいくつかのトリックを適用することでこれをさらに桁違いに減らすいくつかの方法(これにより、この部分が約100 MBになる)を見つけ、このアイデアが機能することを願っています。

さてあなたの答えに関連して:私はループをfuncsで再びロールバックしようとしています、そこでCASはあまり役に立ちませんが、私はすでにいくつかのアイデアを持っています。たとえば、式をのような変数で並べ替え、Python x12, x13,...でを解析し、cscそれらを相互に関連付けるテーブルを生成します。その後、少なくともこれらのパーツをループとして生成できます。これが今のところ最良の解決策であると思われるので、これを最良の回答としてマークします。

ただし、VJoの功績も認めたいと思います。GCC 4.6は実際、はるかにうまく機能し、より小さなコードを生成し、より高速です。大きなモデルを使用すると、コードでそのまま動作します。技術的にはこれが正しい答えですが、コンセプト全体を変更する方がはるかに優れたアプローチです。

皆さんの提案と助けに感謝します。誰か興味があれば、準備ができ次第、最終結果を投稿します。

備考:他のいくつかの回答へのほんの一部の備考:私が実行しようとしているコードは、単純な関数/アルゴリズムの展開と愚かな不必要な展開に由来していません。実際に何が起こるかというと、私たちが始めるのはかなり複雑な数学的オブジェクトであり、それらを数値計算可能な形式にすると、これらの式が生成されます。問題は実際には基礎となる物理理論にあります。中間式の複雑さは、よく知られていますが、これらすべてを物理的に測定可能なもの(観測可能)に組み合わせると、式の基礎を形成するごく一部の非常に小さな関数に要約されます。(「間違った」何かが一般的で、この点で間違いがあるのみ利用可能「摂動論」と呼ばれるansatz)このansatzを別のレベルにしようとします。これは、分析的にはもはや実行できず、必要な関数の基礎が不明です。したがって、このようにブルートフォースにしようとします。最善の方法ではありませんが、うまくいけば、最終的に手元にある物理学の理解に役立つ方法です...

最終編集: すべての提案のおかげで、Mathematicaとfunc上位の回答の行に沿ってsのコードジェネレータの変更を使用して、コードサイズを大幅に縮小することができました:)

cscMathematicaで関数を簡略化し、92 MBまで下げました。これは還元不可能な部分です。最初の試行は永遠にかかりましたが、いくつかの最適化の後、これは単一のCPUで約10分で実行されます。

funcsへの影響は劇的でした:それらの全体のコードサイズは約9 MBに減少しているため、コードは合計で100 MBの範囲になります。最適化をオンにすることは理にかなっており、実行は非常に高速です。

繰り返しますが、皆さんの提案に感謝します。私はたくさん学びました。


17
大量のデータがある場合は、ソースファイルから移動しmmap、実行時に外部バイナリから自分で移動する必要があります。
R .. GitHub ICEのヘルプを停止する

3
これらの機能の1つ(または2つ)の例を挙げていただけますか?これは本当に奇妙に見えます。これらの関数をdl *関数で動的にロードすることもできます。
PatrickSchlüter11年

7
@bbtrb:私の最初の本能はR ..のそれに似ており、デザインの問題のように聞こえます。確かに、科学計算の分野で一般的なことはわかりませんが、誰かが2.8GBのオブジェクトファイル、またはリモートでそれに近いものをリンクしようとしているのを聞いたことがなく、GCCが本当にそれをサポートするかどうかはわかりません。率直に言って、そのサイズのコードblobはすべて純粋なスパゲッティであると期待します。
ニコラスナイト

46
この問題の最適な解決策として、2GBのオブジェクトファイルを使用する方法はまったくありません。
David Heffernan

35
データをコードに入れないでください
デビッドヘファーナン

回答:


53

だから、あなたはすでにこのテキストを生成するプログラムを持っています:

prefactor = +s.ds8*s.ds10*ti[0]->value();
expr = ( - 5/243.*(s.x14*s.x15*csc[49300] + 9/10.*s.x14*s.x15*csc[49301] +
       1/10.*s.x14*s.x15*csc[49302] - 3/5.*s.x14*s.x15*csc[49303] -...

そして

double csc19295 =       + s.ds0*s.ds1*s.ds2 * ( -
       32*s.x12pow2*s.x15*s.x34*s.mbpow2*s.mWpowinv2 -
       32*s.x12pow2*s.x15*s.x35*s.mbpow2*s.mWpowinv2 -
       32*s.x12pow2*s.x15*s.x35*s.x45*s.mWpowinv2 -...

正しい?

すべての関数に同様の「形式」がある場合(n個の数値をm回乗算して結果を追加するか、またはそれに似たもの)、次のようにできると思います。

  • 生成プログラムを変更して、文字列ではなく(つまり、生成される文字列 "s.ds0"の代わりに)オフセットを出力します。 offsetof(ProcessVars, ds0)
  • そのようなオフセットの配列を作成する
  • 上記の配列と構造体ポインタのベースアドレスを受け入れ、結果を生成するエバリュエータを記述します

array + evaluatorは関数の1つと同じロジックを表しますが、コードとなるのはevaluatorのみです。配列は「データ」であり、実行時に生成するか、ディスクに保存してiチャンクを読み取るか、メモリマップファイルを使用できます。

func1の中にあなたの特定の例のためにあなたがのベースアドレスへのアクセスがあった場合、あなたが評価者を経由して機能を書き換えるだろうか想像sしてcscも定数とあなたがに取得するには、ベースアドレスに追加する必要があるオフセットの表現のようなベクトルをx14ds8そしてcsc[51370]

膨大な数の関数に渡す実際のデータを処理する方法を説明する「データ」の新しい形式を作成する必要があります。


45

ABIは、Linuxで使用x86-64では、 GOT及びPLTのための64ビットの再配置タイプを含み、具体的には、サイズの制限を回避するために「大モデル」を定義します。(セクション4.4.2の表、および3.5.5の使用法を示す命令シーケンスを参照してください。)

関数が2.8 GBを使用しているため、gccは大きなモデルをサポートしていないため、運が悪かったです。あなたができることは、動的にリンクする共有ライブラリにコードを分割できるようにコードを再編成することです。

それが不可能である場合、誰かが示唆したように、データをコードに入れる(コンパイルしてリンクする)代わりに、巨大であるため、実行時に(通常のファイルとして、またはmmapして)ロードできます。

編集

ラージモデルはgcc 4.6でサポートされているようです(このページを参照)。あなたはそれを試すことができますが、上記はコードの再編成についても当てはまります。


それで、あなたが言っているのは、オブジェクトファイルをいくつかの小さな共有ライブラリにグループ化すると、制限を克服できるということです。
bbtrb

3
@bbtrbそうです。しかし、私はまだあなたの関数を実装する別の方法を探します。私はあなたのコンパイルが永遠にかかる賭け
BЈовић

18
WTF?このコードは、何らかのスクリプトによって生成される必要があります。メガバイトのコードを手作業で書く人はいません。コードを生成する同じロジックを使用し、計算を実行することもできます。
zvrba

6
gcc 4.6を試すことを強くお勧めします。このプログラムでは、gcc 4.1よりも優れたコードが生成される可能性が非常に高くなります。賢いことを何もすることなく、全体を2GBに圧縮して問題を排除することさえできるかもしれません(-Os、-fwhole-program、-fltoの組み合わせを試してください-このボリュームのコードで、サイズを最適化することは、速度の最適化)。ただし、それでも十分に役に立たない場合は、大きなモデルが機能するためには、大きなモデルのCライブラリ(crt * .o、libc_nonshared.a)の少なくとも一部を再構築する必要があることにも注意してください。 、およびlibpthread_nonshared.a)。
zwol 2011年

1
@bdonlan静的リンクも可能です。
zvrba

37

その側のプログラムでは、コードのキャッシュミスは実行時のループのコストを超える可能性が非常に高くなります。コードジェネレーターに戻って、評価したいもの(つまり、Dキャッシュに収まる可能性が高いもの)のコンパクトな表現を生成し、プログラムのインタープリターで実行することをお勧めします。また、まだかなりの数の操作がある小さなカーネルを除外できるかどうかを確認し、解釈されたコードでそれらを「命令」として使用することもできます。


21

エラーは、データではなくコードが多すぎるために発生します!これは、たとえば__libc_csu_fini(関数である)から参照されていることで示され_start、再配置はそれに合わせて切り捨てられます。これは、_start(プログラムの真のエントリポイント)が2 GBの範囲しかないSIGNED 32ビットオフセットを介してその関数を呼び出そうとしていることを意味します。オブジェクトコードの総量は約2.8 GBであるため、事実を確認してください。

データ構造を再設計できれば、巨大な式を単純なループとして書き直すことにより、コードの多くを「圧縮」することができます。

また、csc[]別のプログラムで計算し、結果をファイルに保存し、必要に応じてロードすることもできます。


単純なループで関数を書き換える方法の例を提供できますか?正確には付いていません。csc[]非常に頻繁に計算する必要があり、ディスクI / Oを回避したいと思います。
bbtrb

4
@bbtr:たとえば、func1上記の場合、次のようになりますfor (int i = 0; i < N; ++i) expr += constants[i].*s.x14*s.x15*csc[49300 + i];
HighCommander4

@ HighCommander4:絶対に同意します。これは、このようなものを自動的に生成する方法の頭上にあります。多分、インデックスを格納する別の配列を使用して...
bbtrb

2
@bbtrb:2.8GBのオブジェクトコードを手動で生成するのに十分なソースを誰もが作成する奇抜な方法はないため、特にこのような非ニーモニックなシンボル名では、コードジェネレーターを使用している必要があります。それで動作します。
ドナルフェロー2011年

15

あなたがやりたいことをするための別の方法があるべきだと皆が同意していると思います。数百メガバイト(ギガバイト?)のコードをコンパイルし、それをマルチギガバイトサイズの実行可能ファイルにリンクして実行すると、非常に非効率的に聞こえます。

私が問題を正しく理解している場合は、何らかのコードジェネレーターGを使用してfunc1...N、一連のマップcsc1...Mを入力として受け取る一連の関数を生成します。実行したいことは、計算してcsc1...M、さまざまな入力に対して1,000,000回のループを実行し、毎回findすることs = func1 + func2 + ... + funcNです。ただし、どのようfucn1...Nに関連してcsc1...Mいるかは指定していません。

それがすべて当てはまる場合は、さまざまな方法で問題を解決できるはずです。これにより、はるかに管理しやすくなり、さらには高速になる可能性があります(つまり、マシンのキャッシュを実際に機能させる)。

オブジェクトファイルサイズの実際的な問題に加えて、現在のプログラムはデータへのアクセスをローカライズせず(巨大なマップが多すぎ)、ローカライズされたコード実行がない(非常に長い関数が多すぎる)ため、効率的ではありません。

プログラムを3つのフェーズに分けてみてください。フェーズ1でビルドcsc1...Mして保存します。フェーズ2は一度に1つずつビルドfuncし、入力ごとに1,000,000回実行して結果を保存します。フェーズ3ではfunc1...N、1,000,000回の実行ごとに、格納された結果の結果の合計を見つけます。このソリューションの良い点は、複数の独立したマシン間で簡単に並列化できることです。

編集:@ bbtrb、1つのfuncと1つのcscを利用できるようにできますか?それらは非常に規則的で圧縮可能であるようです。たとえば、func1は、それぞれが1つの係数、2つのsの変数へのインデックス、1つのcscへのインデックスで構成される式の合計のようです。だから、それは素晴らしいループに減らすことができます。完全な例を利用できるようにすると、長い式ではなくループにそれらを圧縮する方法が見つかるはずです。


はい、あなたは正しく理解しています:)しかし、あなたの提案にはいくつかの問題があります:1.最悪funcのsはほとんどすべてcscのsに依存しており、それらの数値も10 ^ 6回計算する必要があります。2.入力は、適応型モンテカルロインテグレーターから取得されます。つまり、インテグレーターは、必要に応じてポイントの近くのメッシュを細かく調整することにより、結果のエラーを減らすことができるように、各ポイントの完全な結果を知る必要があります。3. csc永続化のための大きな式...
bbtrb

1
それではcsc、各反復で他から独立してそれぞれを計算できないということですか?独立している場合でも、それぞれを10 ^ 6回実行して結果を保存できます。ただし、それらの間に依存関係がある場合は、依存関係グラフのようなものに関連するものを見つけ、それを複数の独立したサブグラフに分割できるかどうかを確認する必要があるかもしれません。全体として、問題は問題を複数の独立した副問題に分割することだと思います。
AlefSin

5

エラーを正しく読んだ場合、制限を引き継ぐのは初期化されたデータセクションです(コードの場合、IMHOのエラーがはるかに多くなります)。グローバルデータの大きな配列はありますか?その場合は、動的に割り当てられるようにプログラムを再構築します。データが初期化されている場合は、構成ファイルから読み取ります。

ところでこれを見て:

(.text + 0x20): `main 'への未定義の参照

別の問題があると思います。


1
はい、あなたは正しい、愚かな間違いですが、それは他のエラーを解決しません。
bbtrb

3

コードはある種の適応深度法を使用して数値積分を行っているように見えます。残念ながら、コードジェネレーター(またはコードジェネレーターの作成者)は、ごとではなくパッチごとに1つの関数を生成するほど愚かです。で、パッチのます。そのため、生成されるコードが多すぎてコンパイルできません。コンパイルできたとしても、どこにも共有されるものがないため、実行は困難です。(オブジェクトコードの各ページをディスクからロードしなければならないことによる痛みを想像できますか?共有されるものは何もないため、常にOSが排除する候補となります。命令キャッシュは何も言わないので、役に立たなくなります。)

修正は、すべての展開を停止することです。この種のコードでは、共有最大化したい、より複雑なパターンでデータにアクセスするための追加命令のオーバーヘッドがとにかく(おそらく)基礎となる大きなデータセットを処理するコストによって吸収されるがあります。また、コードジェネレーターがデフォルトでこれを実行することもあり、科学者が展開のいくつかのオプションを確認し(これらは時々速度が向上することに注意してください)、一度にすべてをオンにし、この結果の混乱が受け入れられると主張しているマシンの実際の制限を受け入れて、デフォルトで生成される数値的に正しいバージョンを使用するのではなく、コンピュータによって。しかし、コードジェネレーターがそれを行わない場合は、それを取得します(または既存のコードをハックします)。

結論 2.8GBのコードのコンパイルとリンクは機能せず、強制的に機能させるべきではありません。別の方法を見つけてください。


3

いくつかの提案:-サイズを最適化(-Os)。インライン関数呼び出し、通常の関数呼び出しを行います。文字列プールを有効にします。

物を別のDLL(共有オブジェクト、Linuxの場合は.so、Mac OS Xの場合は.dylib)に分割してみてください。アンロードできることを確認してください。次に、オンデマンドで物事をロードするために何かを実装し、不要なときにそれらを解放します。

そうでない場合は、コードを異なる実行可能ファイルに分割し、それらの間の通信に何かを使用します(パイプ、ソケット、ファイルへの書き込み/読み取りも)。不器用ですが、どのようなオプションがありますか?

完全代替: -使用して動的言語JIT。私の頭の上の-LuaJITを使用して-これらの式の多くをLuaで書き換える(コードをガベージコレクションできるようにする他の言語やランタイムなど)。

LuaJITは非常に効率的で、特定の状況でC / C ++を打ち負かすことがありますが、非常に近いことがよくあります(ガベージコレクションが不十分なため、速度が遅くなることがあります)。自分で確認してください:

http://luajit.org/performance_x86.html

scimark2.luaそこからファイルをダウンロードし、「C」バージョン(google it)と比較します-多くの場合、結果は非常に近いものです。


2

リンカは、なんらかの理由でこれらの制限を超えたバイナリ内で32ビットの再配置オフセットを生成しようとしています。メインプログラムのアドレス空間要件を減らしてみてください。

オブジェクトコードの一部/ほとんどを1つ以上のライブラリに分割できますか(これも-fpic / -fPICでコンパイルされます)?次に、これらのライブラリにリンクする非静的バイナリを生成します。ライブラリは個別のメモリブロックに存在し、再配置オフセットは相対(32ビット)ではなく動的/絶対(64ビット)になります。


2

これらの表現は、私にとっては交互シリーズのように見えます。残りのコードがどのように見えるのかはわかりませんが、生成式を導出するのはそれほど難しいようには思えません。特に2.8 GBの2 KBのアンロールされたコードがある場合は、実行時にもおそらく価値があります。


1

これは、おそらくシンボリック代数や手動のアンロールによって、コード生成の結果が間違っているように見えます。シンボリック操作は、式ツリーまたは計算グラフの深さで指数関数的に成長することがよく知られています。ここでは自動微分を使用できるため、コードサイズが非常に小さくなり、実行速度が大幅に向上します。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.