Как создать ярлык переменной

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

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 для каждой промежуточной переменной, поэтому, возможно, компилятор более склонен ее оптимизировать. Но, может быть, лучше использовать ссылки?

Ответ 1

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
}

Ответ 2

  • Создайте ваше приложение таким образом, чтобы он не мешал быстрому коду.
  • Напишите свой код, чтобы он был легко читаемым и поддерживаемым.
  • Правильно выполните .
  • Попробуйте узнать, слишком ли он медленный.
  • Если это так, профайл, чтобы увидеть, где он проводит большую часть своего времени.
  • Посмотрите на эти области, чтобы узнать, можно ли повысить производительность при использовании улучшенных алгоритмов.
  • Если все остальное терпит неудачу (и только после этого), начните настраивать код так, как вы просите, в местах, где профилирование оказалось релевантным для приложений Общая производительность. Обычно это будет очень мало пятен.

Ответ 3

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

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

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

Улучшите скорость сразу после профилирования.

Ответ 4

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

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

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

Честно говоря, я не стал бы об этом беспокоиться, просто напишите, какой код выглядит наиболее естественным, и пусть компилятор выполнит эту работу.

Ответ 5

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

Ответ 6

Я бы занялся этим несколько иначе.

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

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;   

Индексные переменные могут быть определены глобально.

Что означают значения в 1 и 30?

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