2012-05-18 14 views
10

Çok uzun (> 10^200) büyük sayıdaki büyük sayılarla ilgilenmem gerekiyor, bu yüzden BigIntegers kullanıyorum. Ben gerçekleştirmek en yaygın operasyon bir akümülatör ekleyerek edilir örn: yıkıcı eylemler için ders verme kopya OfJava, "mutasyona uğramış" BigInteger işlemlerini döngüler halinde optimize edebilir mi?

BigInteger A = new BigInteger("0"); 
for(BigInteger n : nums) { 
    A = A.add(n); 
} 

(kuyu, sürece orada mevcut yeterince büyük bir tampon var gibi), bu yüzden oldu oldukça kaybıdır Java'nın bunu bir şekilde optimize edip edemeyeceğini merak ediyorum (Math.java tarafından açıklanmayan bir MutableBigInteger sınıfı olduğunu duydum) veya kendi BigInteger sınıfımı yazmam gerekip gerekmediğini merak ediyorum.

+8

Oldukça birkaç şekilde dolaylı optimize edebilirsiniz: o (son hariç) o * en * Yeni örneklerini gerçekleştirmek örneğin çok kısa bir süre ve asla onların belleğin nasıl ayrılacağını optimize nedenle yöntemini terk edip, çok canlı. Bu, bu kodun performansını tahmin etmenin çok zor olduğu anlamına gelir. * * * Kodlanmış ve * kanıtlanmış * bu kodun darboğaz olduğunun kanıtı var mı? [Paket org.apache.commons.lang.mutable] (http://commons.apache.org/lang/api-2.4/org/: Eğer bir değişken tamsayı sınıfını kullanmaya gerek yok –

+0

, bakmak yok apache/commons/lang/değişken/paket-summary.html). – anubhava

+0

@anubhava: Bu sınıfların farkında olmak güzel, ancak bu soruya nasıl yardımcı olacaklarını görmüyorum. – NPE

cevap

2

Evet, hesaplama yoğun işlemleri için BigInteger tarafından kullanılan java.math.MutableBigInteger sınıfı vardır. Ne yazık ki, paket özel olarak bildirildiğinden, bunu kullanamazsınız. Ayrıca Apache Commons kütüphanesinde bir "MutableBigInteger" sınıfı vardır, ancak BigInteger için sadece bir değişken sarıcıdır ve bu sizin için bir yardımcı değildir. Java şekilde bu optimize edebilirsiniz eğer

Yukarıda dayanıklı değil ...

Hayır ... merak ediyorum. Ya da kendi BigInteger sınıfımı yazmam gerekip gerekmediğini veya Bu bir yaklaşımdır.

Bir başka OpenJDK kaynaklarını indirmek, java.math.MutableBigInteger için kaynak kodunu bulmak, paket adını ve erişimini değiştirmek ve kod tabanına dahil etmektir. Tek fark, OpenJDK'nın GPL (GPL-2 Sanırım) altında lisanslanması ve modifiye edilmiş bir sınıf kullanarak kod dağıtımı yapması durumunda bunun etkileri vardır.

Ayrıca bakınız:

2

bir hızlı çözüm java paketi görünürlüğünü aşmak etmektir. Sen yapabileceği kendi projede bir paket adında java.math oluşturma ve paket özel MutableBigInteger şöyle ortaya Ortak bir sınıf oluşturarak:

Sonra
package java.math; 

public class PublicMutableBigInteger extends MutableBigInteger { 

} 

sadece java.math.PublicMutableBigInteger alabilir; ve diğer sınıflar olarak kullanın. Bu çözüm hızlıdır ve size belirli bir lisans vermez.

+0

Eğer (java.math' 'içine yeni bir sınıf enjekte ise hangi hala JVM ve/veya java derleyicisi olsa optimize edilmesi yetenekleri genellikle ilgilendiğim erişim kısıtlamasından kaçınmak için "kuralları" ihlal etmek, tüm çete gidebilir ve sınıfların erişimini değiştirebilirsiniz. Aynı fark gerçekten ... –

+0

@Stephen C Ne demeye çalışıyorsun? Ben seni anlamıyorum Java.math içine yeni bir sınıf enjekte etmek kesinlikle daha hızlı ve daha kolaydır. –

+0

Böyle sorunları demek ... http://stackoverflow.com/questions/860187/access-restriction-on-class-due-to-restriction-on-required-library-rt-jar –

2

Derleyicinin yapabileceği pek bir şey yok çünkü add yönteminin ne yaptığını bilemez. İşte döngünün vücudu için oluşturulan kod. Gördüğünüz gibi, add'u çağırır ve sonucu kaydeder.

25: iload 5 
    27: iload 4 
    29: if_icmpge  51 
    32: aload_3 
    33: iload 5 
    35: aaload 
    36: astore 6 
    38: aload_1 
    39: aload 6 
    41: invokevirtual #5; //Method java/math/BigInteger.add:(Ljava/math/BigInteger;)Ljava/math/BigInteger; 
    44: astore_1 
    45: iinc 5, 1 
    48: goto 25 

Teorik olarak, Java sanal makine çalışma zamanı sistemi daha akıllı olabilir. Örneğin, bir nesnenin sürekli olarak sadece tahsis edilmiş bir başkasının üzerine yazdığını ve bunlar için iki ayırma arabelleğini değiştirdiğini tespit edebilir. Biz çöp toplama günlük kaydı etkin şu program çalıştırarak görebilirsiniz Ancak, bu

import java.math.BigInteger; 
import java.util.ArrayList; 
import java.util.Random; 

class Test { 
    public static void main(String[] args) { 
    ArrayList <BigInteger> nums = new ArrayList<BigInteger>(); 
    final int NBITS = 100; 
    final int NVALS = 1000000; 

    System.out.println("Filling ArrayList"); 
    Random r = new Random(); 
    for (int i = 0; i < NVALS; i++) 
     nums.add(new BigInteger(NBITS, r)); 

    System.out.println("Adding ArrayList values"); 
    BigInteger A = new BigInteger("0"); 
    for(BigInteger n : nums) { 
     A = A.add(n); 
    } 

    System.gc(); 
    } 
} 

çöp toplama ekleme işlemi sırasında çağrıları Bkz değil durum ne yazık ki olduğunu.

C:\tmp>java -verbose:gc Test 
Filling ArrayList 
[GC 16256K->10471K(62336K), 0.0257655 secs] 
[GC 26727K->21107K(78592K), 0.0304749 secs] 
[GC 53619K->42090K(78592K), 0.0567912 secs] 
[Full GC 42090K->42090K(122304K), 0.1019642 secs] 
[GC 74602K->65857K(141760K), 0.0601406 secs] 
[Full GC 65857K->65853K(182144K), 0.1485418 secs] 
Adding ArrayList values 
[GC 117821K->77213K(195200K), 0.0381312 secs] 
[GC 112746K->77245K(228288K), 0.0111372 secs] 
[Full GC 77245K->137K(228288K), 0.0327287 secs] 

C:\tmp>java -version 
java version "1.6.0_25" 
Java(TM) SE Runtime Environment (build 1.6.0_25-b06) 
Java HotSpot(TM) 64-Bit Server VM (build 20.0-b11, mixed mode) 
+0

da nasıl tarif edebilir bu montajcı listesini oluşturmak için? –

+0

Sadece '' 'javap -c Test''' çalıştırıyor –

+0

Elbette uyuyor olmalıydım. Bu java bayt kodu, hotspotlar oluşturulan assembler değil. Bu nedenle, jit sihrini gerçekleştirdikten sonra gerçek performans hakkında pek fazla şey söylemez. –

0

Java bu dava için herhangi bir özel optimizasyon yapmayacaktır. BigInteger genel olarak, diğer diziler gibi normal bir sınıf olarak ele alınır (örneğin, String gibi, örneğin, birçok dizeyi birleştirirken bazen bazı özel optimizasyonlar alır).

Ama çoğu durumda

, BigInteger yine önemli olmayacak kadar hızlı yeterlidir. Gerçekten bir sorun olabileceğini düşünüyorsanız, kod yazmanızı ve zamanın ne olduğunu öğrenmenizi tavsiye ederim. BigIntegers ekleyerek tıkanıklık gerçekten ise

, o zaman kudreti mantıklı bir akümülatör gibi davranmaya özel bir değişken büyük tamsayı sınıfını kullanmak. Ama bunu gerçekten ana darboğaz olduğunu kanıtlamadan bunu yapmam.