Как оптимизировать этот фрагмент кода? [Обработка внутри вложенных циклов for]

#java #performance #optimization #runtime

#java #Производительность #оптимизация #время выполнения

Вопрос:

 for (int i = 0,len=size-2; i < len; i  ) {
            for (int j = 1,leng = size-1; j < leng; j  ) {
                for (int k = 2; k < size; k  ) {
                    if (i < j amp;amp; j < k) {
                        sum = sum   Math.floor((a[i]   a[j]   a[k]) /    (a[i] * a[j] * a[k]));
                    }

                }
            }
        }
 

Мне нужно, чтобы этот фрагмент кода выполнялся как минимум за половину текущего времени выполнения.Здесь массив ‘a’ имеет тип double . Я принимаю входные данные через класс reader. Как добиться более быстрого времени выполнения?

Комментарии:

1. Чего вы пытаетесь достичь с помощью этого кода?

2. @MichaelPickett Я должен выполнить суммирование для триплета массива. Код выполняет свою работу. Мне просто нужно, по крайней мере, половину времени выполнения.

3. Мне кажется, что этот код выполняет одно и то же несколько раз. Наиболее примечательно, что каждый i цикл j суммирует и k минус 1 местоположение.

4. @MichaelPickett Я этого не понял. Не могли бы вы уточнить?

5. @Treycos В массиве N элементов. Я должен суммировать триплеты x, y, z так, чтобы 0 <=x<y<z<=N-1.

Ответ №1:

Ваши вложенные циклы ничего не делают, кроме повторения, если условие i < j amp;amp; j < k не выполнено. Но средний и внутренний циклы начинают свои итерации с одного и того же начального значения каждый раз, независимо от значений индексов внешнего цикла. Например, когда i is 5 , средний цикл все еще начинается с 1 , а внутренний цикл все еще начинается с 2 , даже если они могут знать, что они не будут выполнять никакой полезной работы для этих значений.

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

Детали, такие, какие они есть, оставлены в качестве упражнения. Я, вероятно, уже предложил слишком много помощи.

Комментарии:

1. Да, у вас есть. Большое вам спасибо. 🙂

Ответ №2:

Вы можете переписать 1/(x*y*z) как 1*(1/x)*(1/y)*(1/z) . Умножение происходит быстрее, чем деление. Вы можете предварительно вычислить массив обратных значений как ra[i] = 1/a[i] . Могут быть дальнейшие оптимизации, но это зависит от того, какие значения могут быть, вы не ответили на этот вопрос.

Ответ №3:

С этим кодом не будет необходимости в операторе if: x всегда уступает y , который всегда уступает z

 for (int x = 0; x < size - 2; x  )
    for(int y = x   1; y < size - 1; y  )
        for(int z = y   1; z < size; z  )
            sum  = Math.floor((a[x]   a[y]   a[z]) / (a[x] * a[y] * a[z]));
 

Комментарии:

1. Спасибо. Но, к сожалению, это не повлияло на время выполнения.

2. Операция в Math.floor() может занимать около 99% времени выполнения, это единственное, что вы можете улучшить

3. Я не вижу другого пути: (

4. Ммм… зачем вам Math.floor()?, Попробуйте без него и проверьте время выполнения, чтобы увидеть, соответствует ли это pb

5. проблема в том, что оператор floor является частью функции суммирования.