Kesalahan kompilasi GCC dengan kode> 2 GB

108

Saya memiliki sejumlah besar fungsi dengan total sekitar 2,8 GB kode objek (sayangnya tidak ada jalan lain, komputasi ilmiah ...)

Ketika saya mencoba menautkannya, saya mendapatkan relocation truncated to fit: R_X86_64_32Skesalahan (yang diharapkan) , yang saya harap dapat dihindari dengan menentukan flag compiler -mcmodel=medium. Semua perpustakaan yang ditautkan selain yang saya kendalikan dikompilasi dengan -fpicbendera.

Namun, kesalahan tetap ada, dan saya berasumsi bahwa beberapa perpustakaan yang saya tautkan tidak dikompilasi dengan PIC.

Inilah kesalahannya:

/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

Dan pustaka sistem yang saya tautkan:

-lgfortran -lm -lrt -lpthread

Ada petunjuk di mana mencari masalahnya?

EDIT: Pertama-tama, terima kasih untuk pembahasannya ... Untuk sedikit memperjelas, saya memiliki ratusan fungsi (masing-masing berukuran sekitar 1 MB dalam file objek terpisah) seperti ini:

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;
}

Objek srelatif kecil dan membuat diperlukan konstanta x14 itu, x15, ..., DS0, ..., dll sementara tihanya kembali ganda dari sebuah perpustakaan eksternal. Seperti yang Anda lihat, csc[]adalah peta nilai yang telah dihitung yang juga dievaluasi dalam file objek terpisah (lagi-lagi ratusan dengan ukuran masing-masing sekitar ~ 1 MB) dengan bentuk berikut:

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));
    }

    // ...
}

Itu saja. Langkah terakhir kemudian hanya terdiri dari memanggil semua itu func[i]dan menjumlahkan hasilnya.

Mengenai fakta bahwa ini adalah kasus yang agak khusus dan tidak biasa: Ya, benar. Inilah yang harus dihadapi orang ketika mencoba melakukan perhitungan presisi tinggi untuk fisika partikel.

EDIT2: Saya juga harus menambahkan bahwa x12, x13, dll. Sebenarnya bukan konstanta. Mereka ditetapkan ke nilai tertentu, semua fungsi tersebut dijalankan dan hasilnya dikembalikan, dan kemudian set baru x12, x13, dll. Dipilih untuk menghasilkan nilai berikutnya. Dan ini harus dilakukan 10 ^ 5 hingga 10 ^ 6 kali ...

EDIT3: Terima kasih atas saran dan diskusi sejauh ini ... Saya akan mencoba memutar loop pada pembuatan kode entah bagaimana, tidak yakin bagaimana tepatnya, jujur, tapi ini adalah taruhan terbaik.

BTW, saya tidak mencoba bersembunyi di balik "ini adalah komputasi ilmiah - tidak ada cara untuk mengoptimalkan". Hanya saja, dasar untuk kode ini adalah sesuatu yang keluar dari "kotak hitam" di mana saya tidak memiliki akses nyata ke dan, terlebih lagi, semuanya bekerja dengan baik dengan contoh sederhana, dan saya terutama merasa kewalahan dengan apa yang terjadi di dunia nyata. aplikasi dunia ...

EDIT4: Jadi, saya telah berhasil mengurangi ukuran kode cscdefinisi sekitar satu per empat dengan menyederhanakan ekspresi dalam sistem aljabar komputer ( Mathematica ). Sekarang saya juga melihat beberapa cara untuk menguranginya dengan urutan besaran lain atau lebih dengan menerapkan beberapa trik lain sebelum membuat kode (yang akan menurunkan bagian ini menjadi sekitar 100 MB) dan saya harap ide ini berhasil.

Sekarang terkait dengan jawaban Anda: Saya mencoba memutar kembali loop di funcs, di mana CAS tidak akan banyak membantu, tetapi saya sudah punya beberapa ide. Misalnya, mengurutkan ekspresi berdasarkan variabel seperti x12, x13,..., mengurai cscs dengan Python dan menghasilkan tabel yang menghubungkannya satu sama lain. Maka saya setidaknya dapat menghasilkan bagian ini sebagai loop. Karena ini tampaknya menjadi solusi terbaik sejauh ini, saya menandai ini sebagai jawaban terbaik.

Namun, saya juga ingin memberikan penghargaan kepada VJo. GCC 4.6 memang bekerja jauh lebih baik, menghasilkan kode yang lebih kecil dan lebih cepat. Menggunakan model besar berfungsi dengan kode sebagaimana adanya. Jadi secara teknis ini adalah jawaban yang benar, tetapi mengubah keseluruhan konsep adalah pendekatan yang jauh lebih baik.

Terima kasih atas saran dan bantuan Anda. Jika ada yang tertarik, saya akan memposting hasil akhirnya segera setelah saya siap.

KOMENTAR: Hanya beberapa komentar untuk beberapa jawaban lain: Kode yang saya coba jalankan tidak berasal dari perluasan fungsi / algoritme sederhana dan pembukaan gulungan yang tidak perlu dan bodoh. Apa yang sebenarnya terjadi adalah hal-hal yang kita mulai dengan objek matematika yang cukup rumit dan membawanya ke bentuk yang dapat dihitung secara numerik menghasilkan ekspresi ini. Masalahnya sebenarnya terletak pada teori fisika yang mendasarinya. Kompleksitas ekspresi menengah berskala secara faktorial, yang sudah diketahui, tetapi ketika menggabungkan semua hal ini menjadi sesuatu yang dapat diukur secara fisik - yang dapat diamati - itu hanya bermuara pada segelintir fungsi yang sangat kecil yang membentuk dasar ekspresi. (Pasti ada sesuatu yang "salah" dalam hal ini dengan jenderal dan hanya tersediaansatz yang disebut "teori perturbation") Kami mencoba membawa ansatz ini ke level lain, yang tidak lagi layak secara analitis dan dimana dasar dari fungsi yang dibutuhkan tidak diketahui. Jadi kami mencoba memaksa seperti ini. Bukan cara terbaik, tapi semoga cara yang membantu pemahaman kita tentang fisika di tangan pada akhirnya ...

EDIT TERAKHIR: Terima kasih atas semua saran Anda, saya telah berhasil mengurangi ukuran kode secara signifikan, menggunakan Mathematica dan modifikasi generator kode untuk funcs yang agak mirip dengan jawaban teratas :)

Saya telah menyederhanakan cscfungsi dengan Mathematica, menurunkannya menjadi 92 MB. Ini adalah bagian yang tidak dapat direduksi. Upaya pertama memakan waktu lama, tetapi setelah beberapa pengoptimalan, ini sekarang berjalan dalam waktu sekitar 10 menit pada satu CPU.

Efeknya funcdramatis: Seluruh ukuran kode untuk mereka turun menjadi sekitar 9 MB, jadi kode sekarang berjumlah total dalam kisaran 100 MB. Sekarang masuk akal untuk mengaktifkan pengoptimalan dan eksekusinya cukup cepat.

Sekali lagi, terima kasih atas saran Anda, saya telah belajar banyak.

bbtrb.dll
sumber
17
Jika Anda memiliki banyak data, Anda harus memindahkannya dari file sumber dan sebagai gantinya mmapsendiri dari biner eksternal pada waktu proses.
R .. GitHub STOP HELPING ICE
3
Bisakah Anda memberi contoh satu (atau dua) fungsi ini? Ini benar-benar terlihat aneh. Anda juga dapat memuat fungsi ini secara dinamis dengan fungsi dl *.
Patrick Schlüter
7
@bbtrb: Insting pertama saya mirip dengan R .., sepertinya ada masalah desain. Memang, saya tidak tahu apa yang umum dalam lingkaran komputasi ilmiah, tetapi saya belum pernah mendengar seseorang mencoba menautkan file objek 2,8 GB, atau apa pun yang dekat dengannya, dan saya tidak yakin GCC akan benar-benar mendukungnya. Terus terang, saya mengharapkan gumpalan kode apa pun sebesar itu adalah spageti murni.
Nicholas Knight
46
sama sekali tidak mungkin solusi optimal untuk masalah ini melibatkan file objek 2gb.
David Heffernan
35
jangan masukkan data Anda ke dalam kode
David Heffernan

Jawaban:

53

Jadi, Anda sudah memiliki program yang menghasilkan teks ini:

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] -...

dan

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 -...

Baik?

Jika semua fungsi Anda memiliki "format" yang serupa (kalikan n angka m kali dan tambahkan hasilnya - atau yang serupa) maka saya pikir Anda dapat melakukan ini:

  • ubah program generator menjadi offset keluaran alih-alih string (misalnya, alih-alih string "s.ds0", ia akan menghasilkan offsetof(ProcessVars, ds0)
  • membuat array offset tersebut
  • tulis penilai yang menerima larik di atas dan alamat dasar penunjuk struktur dan menghasilkan hasil

Array + evaluator akan mewakili logika yang sama dengan salah satu fungsi Anda, tetapi hanya evaluator yang akan menjadi kode. Array adalah "data" dan dapat dihasilkan saat runtime atau disimpan pada disk dan membaca potongan i atau dengan file yang dipetakan memori.

Misalnya tertentu di func1 membayangkan bagaimana Anda akan menulis ulang fungsi melalui evaluator jika Anda memiliki akses ke alamat dasar sdan cscdan juga vektor seperti representasi dari konstanta dan offset Anda perlu menambahkan ke alamat dasar untuk mendapatkan x14, ds8dancsc[51370]

Anda perlu membuat bentuk baru "data" yang akan menjelaskan cara memproses data aktual yang Anda berikan ke sejumlah besar fungsi.

Andrei
sumber
45

The x86-64 ABI digunakan oleh Linux mendefinisikan "model besar" khusus untuk menghindari keterbatasan ukuran tersebut, yang mencakup 64-bit jenis relokasi untuk GOT dan PLT. (Lihat tabel di bagian 4.4.2, dan urutan instruksi di 3.5.5 yang menunjukkan bagaimana mereka digunakan.)

Karena fungsi Anda menggunakan 2,8 GB, Anda kurang beruntung, karena gcc tidak mendukung model yang besar. Yang dapat Anda lakukan adalah mengatur ulang kode Anda sedemikian rupa sehingga memungkinkan Anda untuk membaginya menjadi pustaka bersama yang akan Anda tautkan secara dinamis.

Jika itu tidak memungkinkan, seperti yang disarankan seseorang, alih-alih memasukkan data Anda ke dalam kode (menyusun dan menautkannya), karena ukurannya sangat besar, Anda dapat memuatnya pada waktu proses (baik sebagai file normal, atau Anda dapat mmap itu).

EDIT

Sepertinya model besar didukung oleh gcc 4.6 (lihat halaman ini ). Anda dapat mencobanya, tetapi hal di atas masih berlaku tentang mengatur ulang kode Anda.

BЈовић
sumber
Jadi apa yang Anda katakan adalah bahwa ketika saya akan mengelompokkan file objek di beberapa perpustakaan bersama kecil, saya akan mengatasi batasan?
bbtrb
3
@bbtr Benar. Tapi saya masih akan mencari cara lain untuk mengimplementasikan fungsi Anda. Saya yakin kompilasi Anda membutuhkan waktu selamanya
BЈовић
18
WTF? Kode ini harus dibuat oleh beberapa skrip; tidak ada yang menulis kode berukuran megabyte dengan tangan! Logika yang sama yang menghasilkan kode juga dapat digunakan untuk menjalankan komputasi.
zvrba
6
Saya sangat menyarankan untuk mencoba gcc 4.6, karena kemungkinan besar akan menghasilkan kode yang lebih baik untuk program ini daripada gcc 4.1; bahkan mungkin dapat memeras semuanya menjadi 2GB tanpa Anda harus melakukan sesuatu yang pintar, menghilangkan masalah (coba kombinasi -Os, -fwhole-program, dan -flto - dengan volume kode ini, mengoptimalkan ukuran adalah mengoptimalkan kecepatan). Namun, jika itu tidak cukup membantu, Anda juga harus menyadari bahwa agar model besar berfungsi, Anda harus membangun kembali setidaknya sebagian pustaka C dalam model besar (crt * .o, libc_nonshared.a , dan libpthread_nonshared.a).
zwol
1
@bdonlan Menghubungkan statis juga dimungkinkan.
zvrba
37

Dengan program dari sisi itu, cache miss untuk kode sangat mungkin melebihi biaya looping saat runtime. Saya akan merekomendasikan agar Anda kembali ke generator kode Anda, dan membuatnya menghasilkan beberapa representasi kompak untuk apa yang ingin dievaluasi (yaitu, yang mungkin cocok dalam D-cache), kemudian jalankan dengan interpreter dalam program Anda. Anda juga dapat melihat apakah Anda dapat memfaktorkan keluar kernel yang lebih kecil yang masih memiliki jumlah operasi yang signifikan, kemudian gunakan itu sebagai 'instruksi' dalam kode yang ditafsirkan.

bdonlan.dll
sumber
21

Kesalahan terjadi karena Anda memiliki terlalu banyak KODE, bukan data! Hal ini ditunjukkan dengan contoh __libc_csu_fini(yang merupakan fungsi) yang direferensikan _startdan relokasi dipotong agar sesuai. Ini berarti bahwa _start(titik masuk sebenarnya program) mencoba memanggil fungsi itu melalui offset 32-bit SIGNED, yang hanya memiliki kisaran 2 GB. Karena jumlah total kode objek Anda ~ 2,8 GB, periksa faktanya.

Jika Anda dapat mendesain ulang struktur data Anda, sebagian besar kode Anda dapat "dikompresi" dengan menulis ulang ekspresi besar sebagai loop sederhana.

Selain itu, Anda dapat menghitung csc[]dalam program lain, menyimpan hasilnya dalam file, dan memuatnya saat diperlukan.

zvrba
sumber
Bisakah Anda memberikan contoh bagaimana Anda akan menulis ulang fungsi dengan loop sederhana? Saya tidak mengikuti Anda dengan tepat. csc[]harus sering dihitung dan saya ingin menghindari I / O disk.
bbtrb
4
@bbtr: Misalnya, untuk func1di atas, sesuatu seperti: for (int i = 0; i < N; ++i) expr += constants[i].*s.x14*s.x15*csc[49300 + i];.
Komandan Tinggi
@ HighCommander4: tentu saja, saya setuju. Ini tepat di atas kepala saya tentang bagaimana menghasilkan sesuatu seperti ini secara otomatis. Mungkin dengan array terpisah yang menyimpan indeks ...
bbtrb
2
@bbtrb: Karena tidak ada cara aneh bahwa siapa pun menulis cukup sumber untuk menghasilkan 2,8 GB kode objek dengan tangan, terutama dengan nama simbol un-mnemonik seperti itu, pembuat kode pasti telah digunakan. Bekerja dengan itu.
Donal Fellows
15

Saya pikir semua orang setuju harus ada cara berbeda untuk melakukan apa yang ingin Anda lakukan. Mengompilasi ratusan megabyte (gigabyte?) Kode, menautkannya ke executable berukuran multi-gigabyte dan menjalankannya terdengar sangat tidak efisien.

Jika saya memahami masalah Anda dengan benar, Anda menggunakan semacam generator kode, G, untuk menghasilkan banyak fungsi func1...Nyang mengambil banyak peta csc1...Msebagai masukan. Apa yang ingin Anda lakukan adalah menghitung csc1...M, dan menjalankan perulangan 1.000.000 kali untuk input berbeda dan setiap kali menemukan s = func1 + func2 + ... + funcN. Anda tidak menentukan bagaimana fucn1...Nberhubungan dengan csc1...M.

Jika semua itu benar, tampaknya Anda harus dapat mengatasi masalah tersebut dengan cara yang berbeda yang berpotensi jauh lebih mudah dikelola dan bahkan mungkin lebih cepat (yaitu membiarkan cache mesin Anda benar-benar berfungsi).

Selain masalah praktis dari ukuran file objek, program Anda saat ini tidak akan efisien karena tidak melokalkan akses ke data (terlalu banyak peta besar) dan tidak memiliki eksekusi kode lokal (terlalu banyak fungsi yang sangat panjang).

Bagaimana jika memecah program Anda menjadi 3 fase: Fase 1 membangun csc1...Mdan menyimpannya. Tahap 2 membangun satu funcper satu, menjalankannya 1.000.000 kali dengan setiap masukan dan menyimpan hasilnya. Tahap 3 menemukan jumlah hasil dari hasil yang disimpan func1...Nuntuk setiap kehabisan 1.000.000 kali. Bagian yang baik tentang solusi ini adalah dapat dengan mudah dibuat paralel di beberapa mesin independen.

Edit: @bbtrb, dapatkah Anda membuat satu func dan satu csc tersedia di sana? Mereka tampaknya sangat teratur dan dapat dimampatkan. Misalnya, func1 tampaknya hanya jumlah ekspresi yang masing-masing terdiri dari 1 koefisien, 2 indeks ke variabel di s dan 1 indeks ke csc. Sehingga bisa direduksi menjadi loop yang bagus. Jika Anda menyediakan contoh lengkap, saya yakin cara dapat ditemukan untuk memampatkannya menjadi loop daripada ekspresi panjang.

AlefSin
sumber
Ya, Anda mengerti dengan benar :) Ada beberapa masalah dengan saran Anda: 1. yang terburuk funcbergantung pada hampir semua cscdan angka-angka itu harus dihitung 10 ^ 6 kali juga. 2. Input akan diperoleh dari integrator Monte Carlo adaptif, artinya integrator harus mengetahui hasil lengkap di setiap titik untuk dapat mengurangi kesalahan yang dihasilkan dengan menghaluskan mesh di sekitar titik jika diperlukan. 3. Ekspresi besar untuk cscbertahan ...
bbtrb
1
Jadi, apakah itu berarti Anda tidak dapat menghitung cscsetiap iterasi secara independen dari yang lain? Jika mereka independen, Anda masih dapat menjalankan masing-masing 10 ^ 6 kali dan menyimpan hasilnya. Namun, jika ada dependensi di antara mereka, mungkin Anda perlu mencari tahu mana yang terkait dengan yang mana, seperti grafik ketergantungan, dan kemudian mencoba melihat apakah Anda dapat memecahnya menjadi beberapa sub-grafik independen. Secara keseluruhan, saya pikir kuncinya adalah memecah masalah menjadi beberapa sub-masalah yang independen.
AlefSin
5

Jika saya membaca kesalahan Anda dengan benar, yang membuat Anda melebihi batas adalah bagian data yang diinisialisasi (jika itu adalah kode, Anda akan memiliki lebih banyak kesalahan IMHO). Apakah Anda memiliki deretan besar data global? Jika demikian, saya akan merestrukturisasi program sehingga dialokasikan secara dinamis. Jika data diinisialisasi, saya akan membacanya dari file konfigurasi.

BTW melihat ini:

(.text + 0x20): referensi tidak terdefinisi ke `main '

Saya pikir Anda memiliki masalah lain.

Pemrogram
sumber
1
Ya, Anda benar, kesalahan bodoh, tetapi itu tidak menyelesaikan kesalahan lainnya.
bbtrb
3

Bagi saya sepertinya kode tersebut melakukan integrasi numerik menggunakan semacam metode kedalaman adaptif. Sayangnya, pembuat kode (atau lebih tepatnya pembuat pembuat kode) sangat bodoh karena menghasilkan satu fungsi per tambalan daripada satu per jenis tambalan. Dengan demikian, itu menghasilkan terlalu banyak kode untuk dikompilasi, dan bahkan jika dapat dikompilasi, eksekusinya akan menyakitkan karena tidak ada yang pernah dibagikan di mana pun. (Dapatkah Anda membayangkan rasa sakit yang diakibatkan karena harus memuat setiap halaman kode objek dari disk karena tidak ada yang pernah dibagikan dan karenanya selalu menjadi kandidat untuk dikeluarkan oleh OS. Untuk tidak mengatakan apa pun tentang cache instruksi, yang akan menjadi tidak berguna.)

Cara mengatasinya adalah berhenti membuka gulungan semuanya; untuk kode semacam ini, Anda ingin memaksimalkan berbagi karena overhead instruksi tambahan untuk mengakses data dalam pola yang lebih kompleks akan diserap oleh biaya untuk menangani (mungkin) kumpulan data pokok yang besar. Mungkin juga pembuat kode akan melakukan ini secara default, dan ilmuwan melihat beberapa opsi untuk membuka gulungan (dengan catatan bahwa ini terkadang meningkatkan kecepatan) dan menyalakan semuanya sekaligus dan sekarang bersikeras bahwa kekacauan yang dihasilkan ini diterima oleh komputer, daripada menerima batasan sebenarnya dari mesin dan menggunakan versi yang benar secara numerik yang dihasilkan secara default. Tetapi jika pembuat kode tidak mau melakukannya, dapatkan yang akan (atau retas kode yang ada).

Intinya: mengompilasi dan menautkan kode 2,8GB tidak berfungsi dan tidak boleh dipaksakan. Temukan cara lain.

Donal Fellows
sumber
3

Beberapa saran: - Optimalkan ukuran (-Os). Lakukan panggilan fungsi sebaris Anda, panggilan fungsi normal. Aktifkan penggabungan string.

Coba bagi semuanya menjadi DLL yang berbeda (objek bersama, .so untuk linux, .dylib untuk Mac OS X). Pastikan mereka dapat diturunkan. Kemudian terapkan sesuatu untuk memuat barang sesuai permintaan, dan membebaskannya saat tidak diperlukan.

Jika tidak, bagi kode Anda menjadi executable yang berbeda, dan gunakan sesuatu untuk berkomunikasi di antara keduanya (pipa, soket, bahkan menulis / membaca ke file). Kikuk, tapi pilihan apa yang Anda miliki?

Benar-benar alternatif: - Gunakan bahasa dinamis dengan JIT . Tepat di atas kepala saya - gunakan LuaJIT - dan tulis ulang ( buat ulang?) Banyak ekspresi ini di Lua , atau bahasa dan runtime lain yang memungkinkan kode untuk dikumpulkan sampah.

LuaJIT cukup efisien, terkadang mengalahkan C / C ++ untuk hal-hal tertentu, tetapi seringkali sangat dekat (terkadang bisa lambat karena pengumpulan sampah yang buruk belum ada). Periksa sendiri:

http://luajit.org/performance_x86.html

Unduh scimark2.luafile dari sana, dan bandingkan dengan versi "C" (google itu) - seringkali hasilnya sangat mirip.

malkia
sumber
2

Linker mencoba untuk menghasilkan offset relokasi 32-bit dalam biner yang entah bagaimana telah melampaui batasan ini. Coba kurangi persyaratan ruang alamat program utama.

Dapatkah Anda membagi beberapa / sebagian besar kode objek menjadi satu atau lebih pustaka (juga dikompilasi dengan -fpic / -fPIC)? Kemudian buat biner non-statis yang terhubung ke libs ini. Perpustakaan akan hidup dalam blok memori diskrit dan offset relokasi Anda akan menjadi dinamis / absolut (64-bit) daripada relatif (32-bit).

ajklbahu8geag.dll
sumber
2

Ekspresi itu terlihat sangat mirip rangkaian bolak-balik bagi saya. Saya tidak tahu seperti apa tampilan kode lainnya, tetapi sepertinya tidak sulit untuk mendapatkan ekspresi yang menghasilkan. Mungkin akan sepadan pada waktu eksekusi juga, terutama jika Anda memiliki 2,8 GB kode 2 KB yang tidak digulung.

Brian
sumber
1

Ini terlihat seperti hasil dari pembuatan kode yang salah, mungkin dengan aljabar simbolis dan / atau pembukaan gulungan manual. Manipulasi simbolik dikenal tumbuh secara eksponensial di kedalaman pohon ekspresi atau grafik komputasi. Sepertinya diferensiasi otomatis dapat digunakan di sini, yang akan membuat ukuran kode menjadi cukup kecil dan juga mempercepat eksekusi secara dramatis.

Jed
sumber