как создать переменную ярлык - PullRequest
1 голос
/ 10 декабря 2010

Предположим, мне нужно создать сложную математическую формулу, например

double f(double array1[100], double array2[100])
{
    double z = array1[21] * array2[3] + array[10];
    double q = array1[21] * array1[30] / array1[10];
    return array1[1] * z * q;
}

или более сложный. Мое решение заключается в создании промежуточных переменных, таких как:

double f(double array1[100], double array2[100])
{
    double energy = array1[21];
    double mass   = array2[3];
    double speed = array[10];
    double z = energy * mass + speed;
    double q = energy * array[30] / speed;
    return array1[1] * z * q;
}

проблема в том, что мне не нужны эти новые переменные, и я не хочу тратить память или увеличивать время на вызов функции. Итак, теперь я использую const для каждой промежуточной переменной, так что, возможно, компилятор более склонен оптимизировать ее. Но, может быть, лучше использовать ссылки?

Ответы [ 6 ]

5 голосов
/ 10 декабря 2010
  1. Дизайн ваше приложение таким образом, чтобы не мешать быстрому коду.
  2. Напишите свой код так, чтобы он был легко читаемым и поддерживаемым .
  3. Сделать так, чтобы он работал правильно .
  4. Проверьте его на и выясните слишком ли это медленно.
  5. Если это так, профилируйте его , чтобы увидеть, где он проводит большую часть своего времени.
  6. Просмотрите эти области, чтобы увидеть, можно ли повысить производительность, улучшив используемых алгоритмов .
  7. Если ничего не помогло (и только потом), начните настройку кода так, как вы просите, в тех местах, где профилирование показало относится к общей производительности приложений.Обычно это будет очень мало мест.
2 голосов
/ 10 декабря 2010

gcc-llvm со стандартной оптимизацией: результаты идентичны без учета перестановки команд

define double @_Z1fPdS_(double* nocapture %array1, double* nocapture %array2) nounwind readonly {
entry:
  %0 = getelementptr inbounds double* %array1, i64 21 ; <double*> [#uses=1]
  %1 = load double* %0, align 8                   ; <double> [#uses=2]
  %2 = getelementptr inbounds double* %array2, i64 3 ; <double*> [#uses=1]
  %3 = load double* %2, align 8                   ; <double> [#uses=1]
  %4 = fmul double %1, %3                         ; <double> [#uses=1]
  %5 = getelementptr inbounds double* %array1, i64 10 ; <double*> [#uses=1]
  %6 = load double* %5, align 8                   ; <double> [#uses=2]
  %7 = fadd double %4, %6                         ; <double> [#uses=1]
  %8 = getelementptr inbounds double* %array1, i64 30 ; <double*> [#uses=1]
  %9 = load double* %8, align 8                   ; <double> [#uses=1]
  %10 = fmul double %1, %9                        ; <double> [#uses=1]
  %11 = fdiv double %10, %6                       ; <double> [#uses=1]
  %12 = getelementptr inbounds double* %array1, i64 1 ; <double*> [#uses=1]
  %13 = load double* %12, align 8                 ; <double> [#uses=1]
  %14 = fmul double %13, %7                       ; <double> [#uses=1]
  %15 = fmul double %14, %11                      ; <double> [#uses=1]
  ret double %15
}

define double @_Z2f2PdS_(double* nocapture %array1, double* nocapture %array2) nounwind readonly {
entry:
  %0 = getelementptr inbounds double* %array1, i64 21 ; <double*> [#uses=1]
  %1 = load double* %0, align 8                   ; <double> [#uses=2]
  %2 = getelementptr inbounds double* %array2, i64 3 ; <double*> [#uses=1]
  %3 = load double* %2, align 8                   ; <double> [#uses=1]
  %4 = getelementptr inbounds double* %array1, i64 10 ; <double*> [#uses=1]
  %5 = load double* %4, align 8                   ; <double> [#uses=2]
  %6 = fmul double %1, %3                         ; <double> [#uses=1]
  %7 = fadd double %6, %5                         ; <double> [#uses=1]
  %8 = getelementptr inbounds double* %array1, i64 30 ; <double*> [#uses=1]
  %9 = load double* %8, align 8                   ; <double> [#uses=1]
  %10 = fmul double %9, %1                        ; <double> [#uses=1]
  %11 = fdiv double %10, %5                       ; <double> [#uses=1]
  %12 = getelementptr inbounds double* %array1, i64 1 ; <double*> [#uses=1]
  %13 = load double* %12, align 8                 ; <double> [#uses=1]
  %14 = fmul double %13, %7                       ; <double> [#uses=1]
  %15 = fmul double %14, %11                      ; <double> [#uses=1]
  ret double %15
}
1 голос
/ 10 декабря 2010

С любым приличным компилятором я очень сомневаюсь, что это имеет значение.

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

Я сомневаюсь, что объявление их const будет иметь какое-то значение, и если вы сделаете для них ссылку, то у них естьв любом случае быть ссылкой на «что-то».

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

1 голос
/ 10 декабря 2010

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

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

Чтобы ответить на ваш вопрос: по возможности избегайте временных объектов, поэтому используйте ссылку.Используйте ключевое слово const, если логически понятно, что переменная является константной, а не по соображениям производительности.

Повышение скорости сразу после профилирования.

0 голосов
/ 10 декабря 2010

Я бы решил это немного по-другому.

Если вы хотите сделать его более читабельным, почему бы не определить некоторые константы

static const unsigned int energy = 21;
static const unsigned int speed = 10;
static const unsigned int mass = 3;

double z = array1[energy] * array2[mass] + array[speed];   
double q = array1[energy] * array1[30] / array1[speed]; 
return array1[1] * z * q;   

Переменные индекса могут быть определены глобально.1007 * Что означают значения в 1 и 30?

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

0 голосов
/ 10 декабря 2010

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...