GCC> 2 GB kodla derleme hatası


108

Toplam 2,8 GB nesne koduna sahip çok sayıda işleve sahibim (maalesef bunun yolu yok, bilimsel hesaplama ...)

Onları bağlamayı denediğimde relocation truncated to fit: R_X86_64_32S, derleyici bayrağını belirterek atlatmayı umduğum (beklenen) hatalar alıyorum -mcmodel=medium. Bağlantılı olan ve benim kontrolümde olan tüm kitaplıklar -fpicbayrakla derleniyor .

Yine de hata devam ediyor ve bağlantı kurduğum bazı kitaplıkların PIC ile derlenmediğini varsayıyorum.

İşte hata:

/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

Ve bağladığım sistem kitaplıkları:

-lgfortran -lm -lrt -lpthread

Sorunu nerede arayacağınıza dair bir ipucu var mı?

DÜZENLEME: Öncelikle, tartışma için teşekkür ederim ... Biraz açıklığa kavuşturmak için, yüzlerce işlevim var (her biri ayrı nesne dosyalarında yaklaşık 1 MB boyutunda) şöyle:

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

Nesne snispeten küçüktür ve gerekli x14, x15, ..., ds0, ... vb. Sabitleri korurken, tiharici bir kitaplıktan bir double döndürür. Gördüğünüz gibi csc[], aşağıdaki formdaki ayrı nesne dosyalarında (yine her biri yaklaşık 1 MB boyutunda yüzlerce) değerlendirilen önceden hesaplanmış bir değer haritasıdır:

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

    // ...
}

Bu onunla ilgili. Son adım daha sonra tüm bunları çağırmak func[i]ve sonucu toplamaktan ibarettir .

Bunun oldukça özel ve alışılmadık bir durum olduğu gerçeğine gelince: Evet, öyle. İnsanların parçacık fiziği için yüksek hassasiyetli hesaplamalar yapmaya çalışırken baş etmesi gereken şey budur.

DÜZENLEME2: Ayrıca x12, x13, vs.'nin gerçekten sabit olmadığını da eklemeliyim. Belirli değerlere ayarlanırlar, tüm bu işlevler çalıştırılır ve sonuç döndürülür ve ardından bir sonraki değeri üretmek için yeni bir x12, x13 vb. Kümesi seçilir. Ve bu 10 ^ 5 ila 10 ^ 6 kez yapılmalıdır ...

DÜZENLEME3: Şimdiye kadarki öneriler ve tartışma için teşekkür ederim ... Dürüst olmak gerekirse, bunu tam olarak nasıl yapacağımı bilmiyorum, ama bu en iyi bahis.

BTW, "bu bilimsel bilgi işlem - optimize etmenin yolu yok" arkasına saklanmaya çalışmadım. Sadece bu kodun temeli, gerçek erişimim olmayan bir "kara kutu" dan çıkan bir şeydir ve dahası, her şey basit örneklerle harika çalıştı ve esas olarak gerçek hayatta olanlarla boğulmuş hissediyorum. dünya uygulaması ...

EDIT4: Böylece, cscbir bilgisayar cebir sistemindeki ( Mathematica ) ifadeleri basitleştirerek tanımların kod boyutunu yaklaşık dörtte bir oranında azaltmayı başardım . Şimdi, kodu oluşturmadan önce başka numaralar uygulayarak (bu bölümü yaklaşık 100 MB'ye indirecek) başka bir büyüklük sırası kadar azaltmanın bir yolunu da görüyorum ve umarım bu fikir işe yarar.

Şimdi yanıtlarınızla ilgili olarak: funcBir CAS'ın pek yardımcı olmayacağı durumlarda döngüleri tekrar yukarı döndürmeye çalışıyorum , ancak zaten bazı fikirlerim var. Örneğin, ifadeleri değişkenlere göre sıralamak x12, x13,..., s'leri cscPython ile ayrıştırmak ve bunları birbiriyle ilişkilendiren tablolar oluşturmak. O zaman en azından bu parçaları döngü olarak oluşturabilirim. Bu şimdiye kadarki en iyi çözüm gibi göründüğünden, bunu en iyi cevap olarak işaretliyorum.

Bununla birlikte, VJo'ya da kredi vermek istiyorum. GCC 4.6 gerçekten çok daha iyi çalışır , daha küçük kodlar üretir ve daha hızlıdır. Büyük modeli kullanmak kodda olduğu gibi çalışır. Yani teknik olarak bu doğru cevap, ancak tüm konsepti değiştirmek çok daha iyi bir yaklaşım.

Önerileriniz ve yardımlarınız için hepinize teşekkür ederim. İlgilenen varsa, hazır olur olmaz nihai sonucu yayınlayacağım.

AÇIKLAMALAR: Bazı diğer yanıtlara birkaç açıklama: Çalıştırmaya çalıştığım kod, basit işlevlerin / algoritmaların genişlemesinden ve aptalca gereksiz kaydırmadan kaynaklanmıyor. Aslında olan şey, başladığımız şeyin oldukça karmaşık matematiksel nesneler olması ve onları sayısal olarak hesaplanabilir bir biçime getirmenin bu ifadeleri oluşturmasıdır. Sorun aslında temelde yatan fiziksel teoride yatıyor. Ara ifadelerin karmaşıklığı faktöriyel olarak ölçeklenir, ki bu gayet iyi bilinmektedir, ancak tüm bunları fiziksel olarak ölçülebilen bir şeyle (gözlemlenebilir) birleştirirken, ifadelerin temelini oluşturan yalnızca bir avuç çok küçük işleve indirgenir. (Bu konuda kesinlikle "yanlış" bir şey var ve yalnızca mevcut"pertürbasyon teorisi" olarak adlandırılan ansatz ) Bu ansatz'ı, analitik olarak artık mümkün olmayan ve ihtiyaç duyulan fonksiyonların temelinin bilinmediği başka bir seviyeye getirmeye çalışıyoruz. Biz de bu şekilde kaba kuvvet yapmaya çalışıyoruz. En iyi yol değil, ama umarım sonunda elimizdeki fizik anlayışımıza yardımcı olacak bir yol ...

SON DÜZENLEME: Tüm önerilerinize teşekkürler, Mathematica kullanarak kod boyutunu önemli ölçüde küçültmeyi başardım ve kod üretecinin funcen iyi cevabın satırları boyunca biraz değiştirilmesini başardım :)

cscMathematica ile fonksiyonları basitleştirip 92 MB'a düşürdüm. Bu indirgenemez kısım. İlk denemeler sonsuza kadar sürdü, ancak bazı optimizasyonlardan sonra bu artık tek bir CPU'da yaklaşık 10 dakika içinde çalışıyor.

E'ler üzerindeki etkisi funcdramatikti: Bunlar için tüm kod boyutu yaklaşık 9 MB'a düştü, bu nedenle kod artık 100 MB aralığında toplanıyor. Şimdi optimizasyonları açmak mantıklı ve yürütme oldukça hızlı.

Hepinize önerileriniz için tekrar teşekkür ederim, çok şey öğrendim.


17
Bu kadar çok veriye sahipseniz, onu kaynak dosyalardan dışarı taşımanız ve bunun yerine mmapçalışma zamanında harici bir ikili dosyadan kendiniz taşımalısınız.
R .. GitHub BUZA YARDIM ETMEYİ DURDUR

3
Bu işlevlerden birine (veya ikisine) bir örnek verebilir misiniz? Bu gerçekten tuhaf görünüyor. Bu fonksiyonları ayrıca dl * fonksiyonu ile dinamik olarak yükleyebilirsiniz.
Patrick Schlüter

7
@bbtrb: İlk içgüdülerim R .. 'lere benziyor, bir tasarım problemi gibi geliyor. Kuşkusuz, bilimsel bilgi işlem çevrelerinde neyin yaygın olduğunu bilmiyorum, ancak 2.8 GB'lık bir nesne dosyasını veya ona uzaktan yakın bir şeyi bağlamaya çalışan birini hiç duymadım ve GCC'nin bunu gerçekten destekleyeceğinden emin değilim. Açıkçası, bu boyuttaki herhangi bir kod bloğunun saf spagetti olmasını beklerdim.
Nicholas Knight

46
Problem için en uygun çözümün 2 gb'lik nesne dosyası içermesinin kesinlikle hiçbir yolu yoktur.
David Heffernan

35
verilerinizi koda koymayın
David Heffernan

Yanıtlar:


53

Yani, bu metni üreten bir programınız zaten var:

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

ve

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

sağ?

Tüm işlevleriniz benzer bir "biçime" sahipse (n sayıyı m kez çarpın ve sonuçları ekleyin - veya benzer bir şey), o zaman bunu yapabileceğinizi düşünüyorum:

  • jeneratör programını dizeler yerine çıkış ofsetlerine değiştirin (yani "s.ds0" dizesi yerine üretecektir offsetof(ProcessVars, ds0)
  • bu tür uzaklıklardan oluşan bir dizi oluşturmak
  • Yukarıdaki diziyi ve yapı işaretçilerinin temel adreslerini kabul eden ve bir sonuç üreten bir değerlendirici yazın

Dizi + değerlendirici, işlevlerinizden biriyle aynı mantığı temsil edecek, ancak yalnızca değerlendirici kod olacaktır. Dizi "veri" dir ve çalışma zamanında üretilebilir veya diske kaydedilebilir ve i yığınlarını okuyabilir veya bellek eşlemeli bir dosyayla birlikte kullanılabilir.

Func1 içinde belirli Örneğin taban adresine erişimi olsaydı bir değerlendirici aracılığıyla işlevini yeniden nasıl hayal sve cscayrıca sabitleri ve almak için baz adreslerine eklemem gerekiyor uzaklıklar temsil gibi bir vektör x14, ds8vecsc[51370]

Çok sayıda işleve aktardığınız gerçek verileri nasıl işleyeceğinizi açıklayan yeni bir "veri" formu oluşturmanız gerekir.


45

ABI Linux tarafından kullanılan X86-64 "büyük bir model" spesifik GOT ve PLT için 64 bit yerleştirme türlerini içerir, örneğin boyut sınırlamaları önlemek için tanımlar. (Nasıl kullanıldıklarını gösteren bölüm 4.4.2'deki tabloya ve 3.5.5'teki talimat dizilerine bakın.)

İşlevleriniz 2,8 GB yer kapladığından, şansınız yok çünkü gcc büyük modelleri desteklemiyor. Yapabileceğiniz şey, kodunuzu dinamik olarak bağlayacağınız paylaşılan kitaplıklara bölmenize izin verecek şekilde yeniden düzenlemektir.

Bu mümkün değilse, birisinin önerdiği gibi, verilerinizi koda koymak (derlemek ve bağlamak) yerine, çok büyük olduğu için, çalışma zamanında yükleyebilirsiniz (ya normal bir dosya olarak ya da onu değiştirebilirsiniz).

DÜZENLE

Görünüşe göre büyük model gcc 4.6 tarafından destekleniyor ( bu sayfaya bakın ). Bunu deneyebilirsiniz, ancak yukarıdakiler kodunuzu yeniden düzenlemek için hala geçerlidir.


Öyleyse, nesne dosyalarını birkaç küçük paylaşımlı kütüphanede gruplandırdığımda, sınırlamaların üstesinden geleceğimi söylüyorsunuz?
bbtrb

3
@bbtrb Doğru. Ama yine de işlevlerinizi uygulamanın başka bir yolunu arardım. Eminim derlemeniz sonsuza kadar sürer
BЈовиЈ

18
O NE LAN? Bu kod, bir komut dosyası tarafından oluşturulmalıdır; kimse megabaytlarca kodu elle yazmaz! Kodu oluşturan mantık aynı zamanda hesaplamayı çalıştırmak için de kullanılabilir .
zvrba

6
Gcc 4.6'yı denemenizi şiddetle tavsiye ederim, bu program için gcc 4.1'den daha üstün bir kod üretme olasılığı çok yüksektir; boyutu için optimize kod hacmi ile - hatta senin sorunu (-OS ait denemek kombinasyonları, -fwhole-programı ve -flto ortadan kaldırarak, akıllı bir şey yapmak zorunda kalmadan 2GB içine her şeyi sıkmak mümkün olabilir olduğunu hız için optimize etme). Ancak, bu yeterince yardımcı olmazsa, büyük modelin çalışması için, büyük modelde (crt * .o, libc_nonshared.a) C kitaplığının en azından bir kısmını yeniden oluşturmanız gerekeceğini bilmelisiniz. ve libpthread_nonshared.a).
zwol

1
@bdonlan Statik bağlantı da bir olasılıktır.
zvrba

37

Bu taraftaki bir programla, kod için önbellekte eksik olanların çalışma zamanında döngü maliyetlerini aşması çok olasıdır. Kod oluşturucunuza geri dönmenizi ve değerlendirilmesini istediği şey için kompakt bir temsil oluşturmanızı (yani, muhtemelen D-önbelleğe sığacak biri), ardından bunu programınızdaki bir yorumlayıcıyla yürütmenizi tavsiye ederim. Ayrıca, hala önemli sayıda işlemi olan daha küçük çekirdekleri çarpanıp atamayacağınızı görebilir, ardından bunları yorumlanan kodda 'talimatlar' olarak kullanabilirsiniz.


21

Hata, veriye değil, çok fazla KODUNuz olduğu için oluşur! Bu, örneğin __libc_csu_fini(bir işlev olan) referans alınarak belirtilir _startve yer değiştirme sığacak şekilde kesilir. Bu, _start(programın gerçek giriş noktasının) bu işlevi yalnızca 2 GB aralığı olan bir İŞARETLİ 32-bit ofset yoluyla çağırmaya çalıştığı anlamına gelir . Nesne kodunuzun toplam miktarı ~ 2.8 GB olduğundan, gerçekler kontrol edilir.

Veri yapılarınızı yeniden tasarlayabilseydiniz, kodunuzun çoğu büyük ifadeleri basit döngüler olarak yeniden yazarak "sıkıştırılabilir".

Ayrıca, csc[]farklı bir programda hesaplayabilir , sonuçları bir dosyada saklayabilir ve gerektiğinde bunları yükleyebilirsiniz.


Basit döngülerle fonksiyonları nasıl yeniden yazacağınıza dair bir örnek verebilir misiniz? Seni tam olarak takip etmiyorum csc[]çok sık hesaplanmalı ve disk G / Ç'sinden kaçınmak istiyorum.
bbtrb

4
@bbtr: Örneğin, için func1yukarıdaki gibi bir şey: for (int i = 0; i < N; ++i) expr += constants[i].*s.x14*s.x15*csc[49300 + i];.
HighCommander4

@ HighCommander4: kesinlikle, katılıyorum. Böyle bir şeyin otomatik olarak nasıl üretileceğine dair kafamın hemen üstünde. Belki ayrı dizi depolayan endeksleri ...
bbtrb

2
@bbtrb: olmadığına göre hiçbir lanet yolu kimse özellikle un-anımsatıcı simge isimlerle, elle nesne kodunun üretim 2.8GB için yeterli kaynak yazdığı bir kod üreteci gerekir kullanılmıştır. Onunla çalışın.
Donal Fellows

15

Bence herkes yapmak istediğini yapmanın farklı bir yolu olması gerektiği konusunda hemfikir. Yüzlerce megabaytlık (gigabayt?) Kodu derlemek, onu çok gigabayt boyutunda bir yürütülebilir dosyaya bağlamak ve çalıştırmak kulağa çok verimsiz geliyor.

Sorununuzu doğru func1...Nanlarsam, csc1...Mgirdi olarak bir grup haritayı alan bir dizi işlev oluşturmak için bir tür kod üreteci, G kullanırsınız . Yapmak istediğiniz şey hesaplamak csc1...Mve farklı girişler için 1.000.000 kez döngü çalıştırmak ve her seferinde bulmaktır s = func1 + func2 + ... + funcN. Bununla nasıl fucn1...Nilişkili olduğunu belirtmedin csc1...M.

Bunların hepsi doğruysa, problemi farklı bir şekilde baştan başa çevirebilmeniz gerektiği görülüyor ki bu potansiyel olarak çok daha yönetilebilir ve hatta muhtemelen daha hızlı olabilir (yani, makinenizin önbelleğinin gerçekten çalışmasına izin vermek).

Nesne dosya boyutlarıyla ilgili pratik problemin yanı sıra, mevcut programınız verilere erişimi yerelleştirmediğinden (çok fazla büyük harita) ve yerelleştirilmiş kod yürütmesine sahip olmadığından (çok fazla çok uzun işlev) verimli olmayacaktır.

Programınızı 3 aşamaya ayırmaya ne dersiniz: Aşama 1 csc1...Mbunları oluşturun ve depolayın. Aşama 2 funcher seferinde bir tane oluşturun, her girişle 1.000.000 kez çalıştırın ve sonuçları kaydedin. Aşama 3 func1...N, 1.000.000 defadan fazla her çalıştırma için depolanan sonuçların sonuçlarının toplamını bulur . Bu çözümün iyi yanı, birkaç bağımsız makinede kolayca paralel yapılabilmesidir.

Düzenleme: @bbtrb, bir yerde bir işlev ve bir csc kullanılabilir yapabilir misiniz? Oldukça düzenli ve sıkıştırılabilir görünüyorlar. Örneğin, func1, her biri 1 katsayı, s içindeki değişkenlere 2 indeks ve csc'ye 1 indeks içeren ifadelerin toplamı gibi görünüyor. Böylece güzel bir döngüye indirgenebilir. Eksiksiz örnekler verirseniz, eminim bunları uzun ifadeler yerine döngülere sıkıştırmanın yolları bulunacaktır.


Evet, doğru anlıyorsunuz :) Önerinizle ilgili birkaç sorun var: 1. En kötü funcs, neredeyse tüm cscs'ye bağlıdır ve bu sayılar da 10 ^ 6 kez hesaplanmalıdır. 2. Girdi, uyarlanabilir bir Monte Carlo entegratöründen elde edilecektir, yani entegratörün, gerekirse noktanın yakınında ağı iyileştirerek ortaya çıkan hatayı azaltabilmesi için her noktada tam sonucu bilmesi gerektiği anlamına gelir. 3. csc
Israrcılığın

1
Öyleyse bu csc, her bir yinelemede diğerlerinden bağımsız olarak her birini hesaplayamayacağınız anlamına mı geliyor ? Bağımsız olsalardı, yine de her birini 10 ^ 6 kez çalıştırabilir ve sonuçları kaydedebilirsiniz. Bununla birlikte, aralarında bağımlılıklar varsa, belki hangisinin hangisiyle ilişkili olduğunu bulmanız gerekir, bir bağımlılık grafiği gibi bir şey ve sonra onu birden fazla bağımsız alt grafiğe bölüp ayıramayacağınızı görmeye çalışın. Sonuç olarak, bence anahtar, sorunu birden çok, bağımsız, alt soruna bölmektir.
AlefSin

5

Hatalarınızı doğru okursam, sınırı aşmanıza neden olan şey başlatılmış veri bölümüdür (eğer kod olsaydı, çok daha fazla hata IMHO olurdu). Büyük küresel veri dizileriniz var mı? Durum buysa, programı dinamik olarak tahsis edilecek şekilde yeniden yapılandırırım. Veriler başlatılırsa, bir yapılandırma dosyasından okurum.

Bunu gören BTW:

(.text + 0x20): "main" e tanımsız başvuru

Sanırım başka bir sorunun var.


1
Evet haklısın, aptalca bir hata, ama diğer hataları çözmüyor.
bbtrb

3

Bana öyle geliyor ki kod, bir çeşit uyarlamalı derinlik yöntemi kullanarak sayısal entegrasyon yapıyor. Ne yazık ki, kod üreteci (veya kod üretecinin yazarı), yama türü başına bir işlev yerine yama başına bir işlev üretecek kadar aptaldır . Bu nedenle, derlenemeyecek kadar çok kod üretti ve derlenebilse bile yürütülmesi acı verici olurdu çünkü hiçbir şey hiçbir yerde paylaşılmaz. (Hiçbir şey paylaşılmadığı için her bir nesne kodu sayfasını diskten yüklemek zorunda kalmanın neden olduğu acıyı hayal edebiliyor musunuz ve bu nedenle işletim sistemi her zaman çıkarılması için bir adaydır. Yararsız olacak talimat önbellekleri hakkında hiçbir şey söylememek.)

Çözüm, her şeyi kaydırmayı durdurmaktır; Bu tür bir kod için, daha karmaşık modellerde verilere erişmek için ekstra talimatların ek yükü, yine de (muhtemelen) büyük temel veri kümesiyle uğraşmanın maliyeti tarafından karşılanacağından paylaşımı en üst düzeye çıkarmak istersiniz . Kod oluşturucunun bunu varsayılan olarak yapması da mümkündür ve bilim adamının bazı açılma seçenekleri görmesi (bunların bazen hızı artırdığı notu ile) ve hepsini aynı anda açması ve şimdi ortaya çıkan bu karmaşanın kabul edilmesi konusunda ısrar etmesi mümkündür. makinenin gerçek kısıtlamalarını kabul etmek ve varsayılan olarak oluşturulan sayısal olarak doğru sürümü kullanmak yerine bilgisayar tarafından. Ancak kod oluşturucu bunu yapmazsa, yapacak bir tane alın (veya mevcut kodu hackleyin).

Sonuç olarak: 2.8GB kodun derlenmesi ve bağlanması işe yaramaz ve çalışmaya zorlanmamalıdır. Başka bir yol bulun.


3

Birkaç öneri: - Boyut için optimize edin (-Os). Satır içi işlev çağrılarınızı, normal işlev çağrılarınızı yapın. Dize havuzunu etkinleştirin.

Öğeleri farklı DLL'lere bölmeyi deneyin (paylaşılan nesneler, linux için .so, Mac OS X için .dylib). Boşaltılabileceklerinden emin olun. Ardından, bir şeyleri talep üzerine yüklemek için bir şeyler uygulayın ve gerekmediğinde bunları serbest bırakın.

Değilse, kodunuzu farklı çalıştırılabilir dosyalara bölün ve aralarında iletişim kurmak için bir şeyler kullanın (borular, soketler, hatta dosyaya yazma / okuma). Sakar ama seçenekleriniz var mı?

Tamamen alternatif: - JIT ile dinamik bir dil kullanın . Kafamın tam üstüne - LuaJIT kullanın - ve bu ifadelerin çoğunu Lua dilinde veya kodun çöp toplanmasına izin veren diğer dillerde ve çalışma zamanlarında yeniden yazın (yeniden üretilsin mi?) .

LuaJIT oldukça etkilidir, bazen belirli şeyler için C / C ++ 'ı yener, ancak çoğu zaman çok yakındır (bazen henüz orada yetersiz çöp toplama nedeniyle yavaş olabilir). Kendiniz kontrol edin:

http://luajit.org/performance_x86.html

scimark2.luaDosyayı buradan indirin ve "C" sürümü (google it) ile karşılaştırın - genellikle sonuçlar çok yakındır.


2

Bağlayıcı, bu sınırlamaları bir şekilde aşan bir ikili dosya içinde 32 bitlik yeniden konum uzaklıkları oluşturmaya çalışıyor. Ana programın adres alanı gereksinimlerini azaltmayı deneyin.

Nesne kodunun bir kısmını / çoğunu bir veya daha fazla kitaplığa bölebilir misiniz (ayrıca -fpic / -fPIC ile derlenir)? Ardından, bu kitaplıklara bağlanan statik olmayan bir ikili dosya oluşturun. Kitaplıklar ayrı bellek bloklarında yaşayacak ve yeniden konumlandırmalarınız göreceli (32 bit) yerine dinamik / mutlak (64 bit) olacaktır.


2

Bu ifadeler bana çok alternatif bir seriye benziyor. Kodun geri kalanının neye benzediğini bilmiyorum ama üreten ifadeyi türetmek o kadar da zor görünmüyor. Muhtemelen yürütme zamanında da buna değecektir, özellikle 2,8 GB 2 KB açılmış kodunuz varsa.


1

Bu, kod üretiminin yanlış gitmesinin sonucuna benziyor, belki de sembolik cebir ve / veya manuel açmayla. Sembolik manipülasyonların, ifade ağacının veya hesaplama grafiğinin derinliğinde üssel olarak büyüdüğü iyi bilinmektedir. Kod boyutunu oldukça küçük hale getiren ve aynı zamanda yürütmeyi önemli ölçüde hızlandıran otomatik farklılaştırma burada kullanılabilir.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.