Изпълнение на метода BigInteger 'add' на телефон с Android

Работих върху криптографски (POT) протокол в Java за магистърската си теза. Той използва криптографски сдвоявания и следователно използва външна библиотека на Java, наречена jPBC (http://gas.dia.unisa.it/projects/jpbc/).

Тъй като искам едната страна на протокола да работи на мобилно устройство, направих прост GUI в Android ADT с един бутон, който стартира протокола. Въпреки това, протоколът работи около 200 пъти по-бавно на моя телефон (Samsung S2 plus, ARM Cortex A9 32-битов процесор), отколкото на моя лаптоп (Intel Core i7, но използва само половин ядро). Тъй като разликата в процесорите може да обясни фактор 10, но със сигурност не фактор 100/200, реших, че разликата в производителността ще се дължи на неефективността на библиотеката jPBC на Android.

Библиотеката jPBC използва широко BigInteger за всичките си изчисления, така че реших да проуча дали BigInteger може да бъде изключително неефективен на android (не е супер ефективен и на нормални компютри). Изпълних цикъл от 1200-битови BigInteger изчисления на телефона и лаптопа. Постигнах някои резултати, които не мога да обясня:

10^6 Събирането и изваждането отнема 205 ms на лаптоп, 48 025 ms на телефон (x 200).

10^5 Умноженията и деленията отнемат 814 ms на лаптоп и 13 705 ms на телефон (x 17).

10^3 модулни експоненции (modPow) отнемат 5079ms на лаптоп и 22 153ms на телефон (x 4,5)

Тъй като има много какво да се каже за тези резултати, ще се придържам към този прост въпрос:

Може ли някой да възпроизведе тези резултати и да потвърди, че добавянето на BigInteger е изключително бавно на Android, или да ми каже какво съм направил погрешно?

Кодът:

Java метод:

public static long bigIntCalculations(){
    System.out.println("starting bigIntCalculations");
    Random random = new Random();
    BigInteger start = new BigInteger(1200, random);
    BigInteger temp = new BigInteger(start.toString());
    long nOfIterations = 1000000L;
    long time1 = System.nanoTime()/1000000;
    for (long i = 0; i < nOfIterations; i++) {
        start = start.add(temp);
        start = start.subtract(temp);

    }
    long result = (System.nanoTime()/1000000)-time1;
    System.out.println(result);
    return result;

}

В Android:

/** Called when the user clicks the button1*/
public void runProtocol(View view) {
long duration = Test.bigIntCalculations();
String result ="Calculations take: " + duration + " ms";    
Intent intent = new Intent(this, DisplayMessageActivity.class);
            intent.putExtra(CALC_RESULT, result);
            startActivity(intent);  
}

Много благодаря!


person Wouter Biesmans    schedule 26.05.2013    source източник
comment
Имам същия проблем с обмена на ключове на DiffieHellman, но не съм сигурен защо получавам по-големи времена за изпълнение ... мисля, че процесорната мощност на смартфон не е толкова добра, колкото на лаптоп. освен това stackoverflow.com /questions/3446540/ може да е намек за решението   -  person cristi _b    schedule 23.06.2013


Отговори (1)


Само x4.5 за 1200-битово модулно степенуване е страхотен резултат, като се има предвид хардуерът с недостатъчна мощност. Това също е доказателство колко лошо е внедряването на BigInteger на JDK.

Стандартната библиотека на Android използва OpenSSL BigNum за някои операции под капака. Без да надничам, бих предположил, че модулното степенуване и модулното обратно действие се обработват в естествен код, докато по-простата аритметика се обработва в Java код.

За тесни цикли на събиране и умножение бихте генерирали много боклук и несъответствието в производителността на GC между платформите също може да окаже голямо влияние -- моето предположение е, че известно загряване + много по-малък бенчмарк ще покаже по-близки резултати.

Проблемът ми с производителността е модулното степенуване, така че съм доста доволен от производителността на Android. Ако това не беше така, щях да гледам пренасянето на библиотеки като gmp4j или gmp-java (две библиотеки с това име) към Android. Две от тях предоставят API, съвместим с BigInteger. Друг предлага по-директно картографиране към GMPLib, което може да бъде идеално по отношение на управлението на паметта (GMP номерата са променливи).

person nadavwr    schedule 24.01.2014