Благодаря этому алгоритму «разделяй и властвуй» (Programming Pearls p80) для нахождения максимальной суммы, найденной в любом непрерывном подвекторе массива, программа на Java работает быстрее, чем аналог C++, протестированный на Win7 x64 с 8 ГБ ОЗУ.
И Java, и C++ работают на 1 ядре ЦП.
Какая оптимизация делается на JVM, чтобы сделать это возможным?
JVM 1 используется:
Версия Java "1.6.0_21"
Java(TM) SE Runtime Environment (сборка 1.6.0_21-b07)
Java HotSpot(TM) 64-разрядная виртуальная машина сервера (сборка 17.0-b17, смешанный режим)
Аргумент виртуальной машины - Xmx12000m
Используется JVM 2: jrockit-jdk1.6.0_24-R28.1.3-4.0.1
Аргумент VM -Xmx12000m
Компилятор С++:
Компилятор Microsoft по умолчанию, который поставляется с Visual Studio 2008 x64.
Время:
//Java JVM 1, Oracle JRE
//0x1fffffff: about 38s, sum 144115187270549505
//0x2fffffff: about 56s, sum 324259171962716161
//0x3fffffff: about 81s, sum 576460750692810753
//Java JVM 2, Oracle JRockit jrockit-jdk1.6.0_24-R28.1.3-4.0.1
//0x1fffffff: about 46s
//0x2fffffff: about 69s
//0x3fffffff: about 95s
//Cpp
//0x1fffffff: around 45s, x64 Release
//0x2fffffff: around 68s, x64 Release sum: 324259171962716161
//0x3fffffff: around 93s, x64 Release sum: 576460750692810753,
final int MAX = 0x3fffffff;
Pearls1 pearls1 = new Pearls1();
pearls1.arr = new int[MAX];
for (int i = 0; i < MAX; i++)
{
pearls1.arr[(int) i] = i;
}
long startTime = System.nanoTime();
long sum = pearls1.binaryForce(0, MAX - 1);
long endTime = System.nanoTime();
long binaryForce(long lower, long upper) {
//std::cout << "binaryForce("<< lower << ","<< upper <<")" << std::endl;
if( lower > upper ) {
return 0;
}
if( lower == upper ) {
return Math.max( 0L, arr[(int) lower] ) ;
}
long middle = ( lower + upper ) /2 ;
long lmax = 0, sum = 0;
for( long i = middle; i >=lower; i-- ) {
sum += arr[(int) i];
lmax = Math.max( lmax, sum);
}
long rmax = 0;
sum = 0;
//for( long i = middle+1; i <= upper; i++ ) {
for( long i = upper; i > middle; i-- ) {
sum += arr[(int) i];
rmax = Math.max(rmax, sum);
}
long theMax = lmax+rmax;
long binarySumLeft = binaryForce(lower, middle);
long binarySumRight = binaryForce(middle+1, upper);
if( theMax > binarySumLeft && theMax > binarySumRight ) {
return theMax;
}
else if( binarySumLeft > theMax && binarySumLeft > binarySumRight ) {
return binarySumLeft;
}
else if ( binarySumRight > theMax && binarySumRight > binarySumLeft ) {
return binarySumRight;
}
else {
return theMax;
}
}
int main(...) {
MAX = 0x3fffffff;
arr = new long[MAX];
for( long i=0;i<MAX;i++) {
//arr[i] = rand();
arr[i] = i;
}
timeb startTime, endTime;
ftime( &startTime);
std::cout << "Start time: " << startTime.time << " sec, " << startTime.millitm << " ms" << std::endl;
sum = binaryForce(0, MAX-1);
std::cout << "sum: " << sum <<std::endl;
ftime( &endTime);
std::cout << "End time: " << endTime.time << " sec, " << endTime.millitm << " ms" << std::endl;
long runTimeSec = endTime.time - startTime.time;
long runTimeMs = endTime.millitm - startTime.millitm;
std::cout << "Run time: " << runTimeSec << " sec, " << runTimeMs << " ms" << std::endl;
}
long long binaryForce(long lower, long upper) {
//std::cout << "binaryForce("<< lower << ","<< upper <<")" << std::endl;
if( lower > upper ) {
return 0;
}
if( lower == upper ) {
return std::max( 0L, arr[lower] ) ;
}
long middle = ( lower + upper ) /2 ;
long long lmax = 0, sum = 0;
for( long i = middle; i >=lower; i-- ) {
sum += arr[i];
lmax = std::max( lmax, sum);
}
long long rmax = 0;
sum = 0;
//for( long i = middle+1; i <= upper; i++ ) {
for( long i = upper; i > middle; i-- ) {
sum += arr[i];
rmax = std::max(rmax, sum);
}
long long theMax = lmax+rmax;
long long binarySumLeft = binaryForce(lower, middle);
long long binarySumRight = binaryForce(middle+1, upper);
if( theMax > binarySumLeft && theMax > binarySumRight ) {
//std::cout << arr[theMax] << std::endl;
return theMax;
}
else if( binarySumLeft > theMax && binarySumLeft > binarySumRight ) {
//std::cout << arr[binarySumLeft] << std::endl;
return binarySumLeft;
}
else if ( binarySumRight > theMax && binarySumRight > binarySumLeft ) {
//std::cout << arr[binarySumRight] << std::endl;
return binarySumRight;
}
else {
//std::cout << arr[theMax] << std::endl;
return theMax;
}
}
long long
в версии C++ иlong
в версии java. 128-битная арифметика определенно будет медленнее. - person Emile Cormier   schedule 26.04.2011/O2
?/DEBUG
? - person James McNellis   schedule 26.04.2011