Я должен попытаться оптимизировать этот метод для своей команды, работая над видеодекодером на Java, хотя я не вижу никакого хорошего подхода к этому. Функция, приведенная ниже, не кажется, что она может ускоряться в любом значительном количестве, поскольку она содержит в основном простое сложение/вычитание/и т.д.
void inverseTransform(int macroBlockIndex, int dataBlockIndex) {
int[] workSpace = new int[64];
short[] data = new short[64];
int z1, z2, z3, z4, z5;
int tmp0, tmp1, tmp2, tmp3;
int tmp10, tmp11, tmp12, tmp13;
int pointer = 0;
for (int index = 8; index > 0; index--) {
if (dataBlockBuffer[pointer + 8] == 0 && dataBlockBuffer[pointer + 16] == 0 && dataBlockBuffer[pointer + 24] == 0 && dataBlockBuffer[pointer + 32] == 0 && dataBlockBuffer[pointer + 40] == 0 && dataBlockBuffer[pointer + 48] == 0 && dataBlockBuffer[pointer + 56] == 0) {
int dcValue = dataBlockBuffer[pointer] << PASS1_BITS;
workSpace[pointer + 0] = dcValue;
workSpace[pointer + 8] = dcValue;
workSpace[pointer + 16] = dcValue;
workSpace[pointer + 24] = dcValue;
workSpace[pointer + 32] = dcValue;
workSpace[pointer + 40] = dcValue;
workSpace[pointer + 48] = dcValue;
workSpace[pointer + 56] = dcValue;
pointer++;
continue;
}
z2 = dataBlockBuffer[pointer + 16];
z3 = dataBlockBuffer[pointer + 48];
z1 = (z2 + z3) * FIX_0_541196100;
tmp2 = z1 + z3 * -FIX_1_847759065;
tmp3 = z1 + z2 * FIX_0_765366865;
z2 = dataBlockBuffer[pointer];
z3 = dataBlockBuffer[pointer + 32];
tmp0 = (z2 + z3) << BITS;
tmp1 = (z2 - z3) << BITS;
tmp10 = tmp0 + tmp3;
tmp13 = tmp0 - tmp3;
tmp11 = tmp1 + tmp2;
tmp12 = tmp1 - tmp2;
tmp0 = dataBlockBuffer[pointer + 56];
tmp1 = dataBlockBuffer[pointer + 40];
tmp2 = dataBlockBuffer[pointer + 24];
tmp3 = dataBlockBuffer[pointer + 8];
z1 = tmp0 + tmp3;
z2 = tmp1 + tmp2;
z3 = tmp0 + tmp2;
z4 = tmp1 + tmp3;
z5 = (z3 + z4) * FIX_1_175875602;
tmp0 = tmp0 * FIX_0_298631336;
tmp1 = tmp1 * FIX_2_053119869;
tmp2 = tmp2 * FIX_3_072711026;
tmp3 = tmp3 * FIX_1_501321110;
z1 = z1 * -FIX_0_899976223;
z2 = z2 * -FIX_2_562915447;
z3 = z3 * -FIX_1_961570560;
z4 = z4 * -FIX_0_390180644;
z3 += z5;
z4 += z5;
tmp0 += z1 + z3;
tmp1 += z2 + z4;
tmp2 += z2 + z3;
tmp3 += z1 + z4;
workSpace[pointer + 0] = ((tmp10 + tmp3 + (1 << F1)) >> F2);
workSpace[pointer + 56] = ((tmp10 - tmp3 + (1 << F1)) >> F2);
workSpace[pointer + 8] = ((tmp11 + tmp2 + (1 << F1)) >> F2);
workSpace[pointer + 48] = ((tmp11 - tmp2 + (1 << F1)) >> F2);
workSpace[pointer + 16] = ((tmp12 + tmp1 + (1 << F1)) >> F2);
workSpace[pointer + 40] = ((tmp12 - tmp1 + (1 << F1)) >> F2);
workSpace[pointer + 24] = ((tmp13 + tmp0 + (1 << F1)) >> F2);
workSpace[pointer + 32] = ((tmp13 - tmp0 + (1 << F1)) >> F2);
pointer++;
}
pointer = 0;
for (int index = 0; index < 8; index++) {
z2 = workSpace[pointer + 2];
z3 = workSpace[pointer + 6];
z1 = (z2 + z3) * FIX_0_541196100;
tmp2 = z1 + z3 * -FIX_1_847759065;
tmp3 = z1 + z2 * FIX_0_765366865;
tmp0 = (workSpace[pointer + 0] + workSpace[pointer + 4]) << BITS;
tmp1 = (workSpace[pointer + 0] - workSpace[pointer + 4]) << BITS;
tmp10 = tmp0 + tmp3;
tmp13 = tmp0 - tmp3;
tmp11 = tmp1 + tmp2;
tmp12 = tmp1 - tmp2;
tmp0 = workSpace[pointer + 7];
tmp1 = workSpace[pointer + 5];
tmp2 = workSpace[pointer + 3];
tmp3 = workSpace[pointer + 1];
z1 = tmp0 + tmp3;
z2 = tmp1 + tmp2;
z3 = tmp0 + tmp2;
z4 = tmp1 + tmp3;
z5 = (z3 + z4) * FIX_1_175875602;
tmp0 = tmp0 * FIX_0_298631336;
tmp1 = tmp1 * FIX_2_053119869;
tmp2 = tmp2 * FIX_3_072711026;
tmp3 = tmp3 * FIX_1_501321110;
z1 = z1 * -FIX_0_899976223;
z2 = z2 * -FIX_2_562915447;
z3 = z3 * -FIX_1_961570560;
z4 = z4 * -FIX_0_390180644;
z3 += z5;
z4 += z5;
tmp0 += z1 + z3;
tmp1 += z2 + z4;
tmp2 += z2 + z3;
tmp3 += z1 + z4;
data[pointer + 0] = (short) ((tmp10 + tmp3) >> F3);
data[pointer + 7] = (short) ((tmp10 - tmp3) >> F3);
data[pointer + 1] = (short) ((tmp11 + tmp2) >> F3);
data[pointer + 6] = (short) ((tmp11 - tmp2) >> F3);
data[pointer + 2] = (short) ((tmp12 + tmp1) >> F3);
data[pointer + 5] = (short) ((tmp12 - tmp1) >> F3);
data[pointer + 3] = (short) ((tmp13 + tmp0) >> F3);
data[pointer + 4] = (short) ((tmp13 - tmp0) >> F3);
pointer += 8;
}
short[] temp = imageSlice.MacroBlocks[macroBlockIndex].DataBlocks[dataBlockIndex];
for (int i = 0; i < data.length; i++)
temp[i] = data[i]; //imageSlice.MacroBlocks[macroBlockIndex].DataBlocks[dataBlockIndex][i] = data[i];
}
Должен ли я объединить базовую математику, если смогу, или что бы вы предложили?
Я не вижу ничего очевидного. В дополнение к тому, что сказал Алекс, есть два небольших предложения, которые могут помочь:
1) Оператор long if
в первом цикле имеет ряд условий отказа. Вы заказали его так, чтобы сперва было сбой? С оценкой короткого замыкания, чем раньше вы можете найти false
тем меньше работы нужно сделать для оценки всего выражения.
2) Вы объявляете множество переменных за пределами двух циклов for-loops, и я могу понять, почему вы это сделали. Возможно, что JVM будет более способна оптимизировать ситуацию, если вы перемещаете объявления внутри двух циклов, чтобы переменные объявлялись как можно локальнее.
Для обоих из них вам нужно выполнить некоторые тайминги, чтобы увидеть, имеют ли они реальную разницу. Вы также можете использовать профилировщик, чтобы увидеть, где код проводит большую часть своего времени.
У меня есть еще один комментарий. В строках типа:
data[pointer + 7] = (short) ((tmp10 - tmp3) >> F3);
вы используете >>
вместо >>>
для битвыдвижения, возможно, отрицательного числа. Вы уверены, что это то, что вы хотите сделать, если tmp3> tmp10?
Как и другие плакаты, я думаю, что вы можете сделать это очень мало, чтобы оптимизировать это как таковое.
Я просто попытаюсь прочесть все значения (dataBlockBuffer [x]) в локальные переменные перед состоянием, а затем изменить ваше условие на:
if ((data0 | data1 | data2 |...) == 0)...
Таким образом, у вас потенциально меньше ветвей и где условие терпит неудачу (предположительно большую часть времени?), Данные уже готовы к локальным переменным.
Но это говорит, я не думаю, что вы сильно побритесь.
Еще одна очень незначительная вещь, которую следует учитывать, заключается в том, что упаковка ByteBuffer вокруг массива позволяет вам потенциально читать/записывать сразу несколько значений, если вы можете увидеть способ сделать это. (По крайней мере, когда вы пишете "dcValue" несколько раз, вы можете написать длинный вместо этого, если компилятор JIT не сделает эту оптимизацию).
На рабочем столе я мог бы подумать:
Я бы рассмотрел последние два как "экстремальные" варианты anyway-- с риском инвестирования значительного времени для небольшого выигрыша.
Без конкретных доказательств проблем с производительностью я могу увидеть пару возможных улучшений (хотя не знаю, какое улучшение вы получите от них).
pointer+7
повторяется несколько раз. Вы можете рассчитать его один раз.System.arraycopy()
для копирования массива в конце.