Эквивалент инкремента указателя C / C ++ в Java? - PullRequest
4 голосов
/ 14 марта 2011

У меня действительно есть чувство, что люди будут пытаться избить меня по голове и сказать: "Ты не должен этого делать!"(и я вполне осознаю этот факт);тем не менее, вот моя проблема:

Предположим, у вас есть следующий код C ++:

РЕДАКТИРОВАТЬ: Я думаю, что я не показал достаточно того, что я пытаюсьделать, хотя большинство ответов было превосходным.Итак, вот отредактированная версия моего кода.Суть в том, что на каждой итерации мне все еще нужно использовать массив значений, который оказывается подмассивом x, а не просто одним значением индекса:

unsigned int n = 2000; // or any other number for that matter
double * x = new double[n];
double resultArray;

// fill array with meaningful data
// do all kinds of initializations

for( int i=0 ; i<someNumber ; ++i ){ //someNumber ~ 1900

    // do some stuff

    for (j=0 ; j<someSmallerNumber ; ++j){ //someSmallerNumber ~ 15
        resultArray[j] = x[j] * someFunction(resultArray[j]);
    }

    ++x; //increment pointer to the first element of the array

    // do some more stuff

}

РЕДАКТИРОВАНИЕ: Причина, по которой я использую ++x во внешнем цикле, заключается в том, что если бы я использовал x[outerIndex+innerIndex] вместо просто x[innerIndex], я бы выполнил много больше дополненийза одну итерацию, и это алгоритм, тяжело работающий с алгеброй, поэтому я пытаюсь выжать из него некоторую производительность.

Я хотел бы отметить, что мой алгоритм никогда не пытается читать несуществующую память.Это просто проблема скорости обработки, когда я пытаюсь не пересчитывать текущий индекс массива больше, чем нужно.Это работает отлично, и я доволен этим.

Теперь я пытаюсь реализовать подобный алгоритм в Java (и Java не в моей области знаний).Однако я знаю, что Java на самом деле не дает вам доступа к указателям и обрабатывает все как объект.Мой вопрос, конечно, есть ли эффективный способ выполнить эквивалент ++x, где x - это адрес первого элемента массива в Java?Есть ли способ удалить первый элемент массива вместо этого?Есть ли хорошие быстрые алгоритмы, на которые стоит обратить внимание, если они не являются частью встроенных манипуляций с массивами Java?

Заранее спасибо!=)

Ответы [ 5 ]

4 голосов
/ 14 марта 2011

Java это не C ++.То, что вы делаете в C ++ для увеличения скорости, не обязательно относится к Java.Это один из таких случаев.

Использование for (int val: x) в Java не даст, как некоторые люди, даст вам какое-либо преимущество перед:

for(int i = 0; i < x.length; i++)
{
    int val = x[i];
}

Ссылка здесь;http://java.sun.com/docs/books/jls/third_edition/html/statements.html#14.14.2

То, что люди говорят здесь о виртуальной машине, можно свободно оптимизировать во время выполнения, это правильно.

Итак, да, вам нужно немного побить голову: -).Хотя Java и C ++ выглядят одинаково, то, что вы делаете в одном, не то, что вы делаете в другом во всех случаях: чтобы писать хорошую Java, вы должны думать с точки зрения Java;для C ++ вы должны думать с точки зрения C ++.

4 голосов
/ 14 марта 2011

Используйте цикл for-each: for (double d : theArray) - это идиоматический способ сделать это, и он дает ВМ самые ясные возможности оптимизации.

Если ваше условие прерывания зависит от текущей позиции в массиве, вам, вероятно, лучше всего использовать классический цикл for с рукописным счетчиком - извините.

3 голосов
/ 14 марта 2011

Эффективный способ - использовать индекс и увеличивать его в цикле.

JIT имеет право поднимать проверки границ вне цикла, если он может доказать, что сам по себе удовлетворен тем, что переменная индексапросто охватывает диапазон упорядоченным образом.В вашем случае JIT может быть трудно доказать, что someSmallerNumber всегда достаточно мал, но все еще может подниматься за пределы внутреннего цикла.как только он проверил someSmallerNumber один раз за внешний цикл.

Для простейшего случая, с так называемым «для каждого», даже если компилятор испускает байт-код, который использует индекс внутри (я незнать, делает это или нет), то JIT должен немедленно увидеть, что индекс никогда не может быть вне границ.

, если я использовал x [externalIndex + innerIndex] вместо просто x [innerIndex] Iбудет выполнять гораздо больше сложений за итерацию

Нет гарантии, что JIT тупее, чем вы - он может хранить значения многократно используемых частичных вычислений в регистрах, если он этого хочет.Боюсь, я не знаю, обнаружит ли на практике JIT, что x[outerIndex+innerIndex] можно вычислить по-разному, повторно используя адрес в середине массива.Повторно используемое значение не является GC-способным указателем, добавляет сложность, бла-бла, поэтому оно может или не может быть в состоянии точно такой же оптимизации, которую вы сделали в C ++.Но хороший оптимизатор C ++, вероятно, способен выполнять оптимизацию без вашей помощи, поэтому я даже не удивлюсь, если JIT тоже сможет.

2 голосов
/ 14 марта 2011

Краткий ответ: прямого эквивалента нет.

Используйте индексы или используйте for (double d : array_of_double) - конструкция for упрощает оптимизацию ВМ.

0 голосов
/ 14 марта 2011

Довольно часто встречаемая мной идиома заключается в том, чтобы прочитать значение из массива и сохранить его в локальной переменной, манипулировать этой локальной переменной и, наконец, сохранить результат обратно:

for (int i = 0; i < someNumber; ++i)
{
    double val = x[i];

    // do heavy lifting with val

    x[i] = val;
}

Конечно, если вы только читаете из массива, вам не нужно записывать значение обратно.В этом случае просто используйте цикл for-each:

for (double val : x)
{
    // ...
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...