Что это самый быстрый способ найти максимум двух поплавков в C ++?

голоса
1

Что это самый быстрый способ найти максимум двух поплавков:

а)

y = std::max(x1, x2);

б)

if (x1 > x2)
    y = x1;
else
    y = x2;

с)

y = x1 > x2 ? x1 : x2;

благодаря

Задан 19/05/2009 в 14:40
источник пользователем
На других языках...                            


13 ответов

голоса
2

B и C будет компилировать же , по крайней мере , в теории. Я выбираю те , потому что , если std::maxне будет не функция вызова (например, макро), тем будет самым быстрым.

Редактировать Видимо, std::maxэто вызов функции шаблона , как ваша форма C. http://www.cplusplus.com/reference/algorithm/max/

Ответил 19/05/2009 в 14:42
источник пользователем

голоса
24

Вот другой вопрос

Почему вы думаете, такая небольшая оптимизация будет иметь значение в более широком контексте вашей программы?

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

EDIT Добавление некоторых разъяснений похоронены в комментариях

Причина нет большого ответа на этот вопрос в том, что выполнение этого кода сильно зависит от ...

  1. Путь, в котором он используется в вашей программе
  2. Частности компилятор вы используете
  3. Флаги оптимизации передается компилятором
  4. Частности архитектуры вы работаете код на
  5. Многие другие очень маленькие вещи, которые не были включены в вопросе

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

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

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

Ответил 19/05/2009 в 14:44
источник пользователем

голоса
4

Это компилятор конкретного, но я подозреваю, что результат будет таким же. Посмотрите на выходе сборки компилятора.

Ответил 19/05/2009 в 14:45
источник пользователем

голоса
2

То же наблюдение, как обычно, когда речь идет о «быстром». Вы измерить время выполнения вами максимальный расчет, сообщили в остальное время выполнения процесса? Означает ли это «оптимизация» решение оказать существенное влияние на время выполнения приложения?

Я 99% уверен, что разница между вашими предложениями не стоит рассматривать.

Ответил 19/05/2009 в 14:45
источник пользователем

голоса
4

Вы можете проверить это самостоятельно в вашей системе.

Я сделал это для вас на GCC - RedHat. Результаты по моей системе, для 100000 казней с x1 = 432943.5 и х2 = 434232.9

а) ~ 1200 мксек б) ~ 600 мксек с) ~ 600 мксек

EDIT: С -O2 оптимизации я получил те же результаты во всех 3 -х случаях: ~ 110 мксек.

Конечно, фактический результат зависит от многих факторов, в вашей конкретной проблеме и системе.

Ответил 19/05/2009 в 14:45
источник пользователем

голоса
2

Единственный способ, чтобы действительно знать, чтобы измерить их. Они могут варьироваться в зависимости от компиляторов или платформ на платформу.

Выполнить петлю каждого на 100000 или 500000 итераций и сравнить общее время выполнения.

Ответил 19/05/2009 в 14:45
источник пользователем

голоса
2

Benchmark их и выяснить.

Ответил 19/05/2009 в 14:46
источник пользователем

голоса
0

Распространено #defineлибо б или с макросом, и использовать его на протяжении всего кода. Обратите внимание , что это работает только в большинстве случаев, и умрет , если вы передаете в й или у аргумента , модифицированный без идемпотентного оператора или функции вызова с побочными эффектами. Например:

#define MAX(x,y) (((x) < (y)) ? (y) : (x))
...
MAX(i++, ++j); //won't work properly, the ++'s will get executed twice.
MAX(changeKSomehow(k), changeLSomehow(L)); //won't work, the functions will get called twice.

Оказывается, что зЬй :: макс, по крайней мере , для GNU libstdc ++ реализован почти одинаково, и использует inlineподсказку. Компилятор должен быть в состоянии взять подсказку , когда это необходимо (когда <оператор принимает достаточно несколько инструкций , чтобы не вызвать огромное количество I $ давления , если встраиваемым).

Ответил 19/05/2009 в 14:48
источник пользователем

голоса
1

И этот путь может быть лучше?

y = x1;
if (y < x2)
    y = x2;

Удаление состояния еще может быть лучше интерпретировать компилятор.

Edit1: Если бенчмаркинг не забудьте сделать половину теста с x1 больше чем x2, а другая половина с х2 большего. В противном случае результаты не будут отражать реальные случаи.

Edit2: Microoptimazions как-то полезно, если вы работаете во встраиваемых системах с 1 или 2k памяти. А также, сво межжала проблема думать, почему тайминги различны в каждом конкретном случае.

Ответил 19/05/2009 в 14:48
источник пользователем

голоса
4

-O3 Двухъядерный Macbook Pro 2.4GHz

станд :: макс (x1, x2) Время: 4,19488 RMAAx-х: 4,19613 если время: 4.18775? Время: 4,18831

станд :: макс (x1, x2) Время: 4,1836 RMAAx-х: 4,18274 если время: 4.18603? Время: 4,18857

станд :: макс (x1, x2) Время: 4,18714 RMAAx-х: 4,18759 если время: 4.19752? Время: 4,19797

станд :: макс (x1, x2) Время: 4,1926 RMAAx-х: 4,19293 если время: 4.19334? Время: 4,19626

станд :: макс (x1, x2) Время: 4,18963 RMAAx-х: 4,19628 если время: 4.19253? Время: 4,19107

#include <iostream>

using namespace std;

int main (int argc, char * const argv[]) {

    uint64_t iterations = 10000000000;
    float x1 = 3455.232;
    float x2 = 7456.856;
    float y = 0;

    for (int count = 0; count < 5; ++count)
    {       
        clock_t begin_time = clock();
        for (uint64_t ii = 0; ii < iterations; ++ii)
        {
            y = std::max(x1, x2);
        }

        std::cout << "std::max(x1, x2) Time: " << float( clock () - begin_time ) /  CLOCKS_PER_SEC << endl;


        begin_time = clock();
        for (uint64_t ii = 0; ii < iterations; ++ii)
        {
            y = x1;
            if (y < x2)
                y = x2;
        }

        std::cout << "RMAAx's : " << float( clock () - begin_time ) /  CLOCKS_PER_SEC << endl;


        begin_time = clock();
        for (uint64_t ii = 0; ii < iterations; ++ii)
        {
            if (x1 > x2)
                y = x1;
            else
                y = x2;
        }

        std::cout << "if Time: " << float( clock () - begin_time ) /  CLOCKS_PER_SEC << endl;


        begin_time = clock();
        for (uint64_t ii = 0; ii < iterations; ++ii)
        {
            y = x1 > x2 ? x1 : x2;
        }

        std::cout << "? Time: " << float( clock () - begin_time ) /  CLOCKS_PER_SEC << endl;
    }

    return 0;
}
Ответил 19/05/2009 в 16:03
источник пользователем

голоса
2

Во- первых, как уже говорили другие, свой код и сделать абсолютный уверен , что это что - то стоит оптимизировать. Если да, то читайте дальше: вы можете сделать это без ветвления. См долой fcmp: Условный Moves Для внеофисном Math для получения более подробной информации.

Ответил 19/05/2009 в 16:44
источник пользователем

голоса
3

Intel x86 имеет инструкции (FCOMI / FCOMIP / FUCOMI / FUCOMIP) , которые обеспечивают быстрое сравнение значений с плавающей точкой. Ваш процессор может иметь такие инструкции тоже. Хитрость заключается в выяснении, что C ++ писать для того , чтобы максимально увеличить шансы вашего компилятора , используя эти инструкции вместо того , чтобы делать что - то медленнее , но более общее.

Оптимистический предложение заключается в использовании зЬй :: макс (поплавка, поплавок) в надежде, что кто-то игнорировали те, кто дразнить «microbenchmark» и «преждевременной оптимизации» и сделать необходимые исследования, чтобы обеспечить специализацию станд :: макс (поплавок , поплавок), который будет использовать специализированные инструкции вашего оборудования.

Ответил 19/05/2009 в 20:24
источник пользователем

голоса
0

При наличии приличного оптимизатора, они эквивалентны.

Ответил 19/05/2009 в 22:51
источник пользователем

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more