Логическая ошибка синхронизации в C ++ (с использованием std :: chrono) - PullRequest
0 голосов
/ 03 октября 2019

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

Сначала я создал класс для синхронизации алгоритмов, используя конструктор и деструктор. Затем я использовал std::chrono::time_point_cast для явного приведения времени к миллисекундам. Тем не менее, программа заканчивала тем, что показывала нулевые миллисекунды каждый раз, когда я запускаю свою программу.

Обратите внимание, что я включил файл заголовка хронографа.

Вот часть исходного кода программыкод.

Определение класса

int Array[20], size = 20;

class BenchmarkTimer
{
public:
    std::chrono::time_point<std::chrono::high_resolution_clock> startpt;
    float ms;
    long long duration;
    BenchmarkTimer() : ms(0), duration(0)
    {
        startpt = std::chrono::high_resolution_clock::now();
    }
    ~BenchmarkTimer()
    {
        auto endpt = std::chrono::high_resolution_clock::now();
        auto init = std::chrono::time_point_cast<std::chrono::milliseconds>(startpt).time_since_epoch().count();
        auto final = std::chrono::time_point_cast<std::chrono::milliseconds>(endpt).time_since_epoch().count();
        auto duration = final - init;
    }
};

Функция сортировки выбора (это только один из многих алгоритмов сортировки).

void SelectionSort(int Array[])
{
    BenchmarkTimer timer;
    int temp, smallest, position, j;
    for (int i = 0; i < size - 1; i++)
    {
        smallest = Array[i];
        position = i;
        for (j = i + 1; j < size; j++)
            if (Array[j] < smallest)
            {
                smallest = Array[j];
                position = j;
            }
        temp = Array[i];
        Array[i] = Array[position];
        Array[position] = temp;
    }
    DisplayArray(Array);
    std::cout << "\nTime taken to sort the array: " << timer.duration << " ms" << std::endl;
}

Вызов функции DisplayArray(Array) просто отображаетмассив на экране.

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

Прямо сейчас фактический вывод:

Time taken to sort the array: 0 ms

Но яЯ хочу, чтобы вывод был:

Time taken to sort the array: 13 ms

(13 мс - это просто пример.)

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

Заранее спасибо!

Ответы [ 2 ]

1 голос
/ 03 октября 2019

Один очень простой способ решить эту проблему - просто поместить оператор печати для таймера в ~BenchmarkTimer(). Конструктор BenchmarkTimer может принять сообщение для увеличения вывода в ~BenchmarkTimer(). Это может выглядеть следующим образом:

class BenchmarkTimer
{
public:
    std::string msg_;
    std::chrono::steady_clock::time_point startpt_;

    explicit BenchmarkTimer(std::string msg)
        : msg_(std::move(msg))
        , startpt_(std::chrono::steady_clock::now())
    {
    }

    ~BenchmarkTimer()
    {
        using namespace std::chrono;
        auto endpt = steady_clock::now();
        std::cout << msg_ << duration_cast<milliseconds>(endpt - startpt_).count() << " ms\n";
    }

    BenchmarkTimer(BenchmarkTimer const&) = delete;
    BenchmarkTimer& operator=(BenchmarkTimer const&) = delete;
};

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

void SelectionSort(int Array[])
{
    BenchmarkTimer timer{"\nTime taken to sort the array: "};
    int temp, smallest, position, j;
    // ...
    DisplayArray(Array);
}  // Output: Time taken to sort the array: 13 ms
1 голос
/ 03 октября 2019

Ваша проблема здесь в том, что вы рассчитываете время только в деструкторе BenchmarkTimer. Это означает, что duration всегда будет 0, поскольку он изменяется только в деструкторе, и вы не можете получить доступ к объекту после его разрушения.

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

class BenchmarkTimer
{
public:
    std::chrono::time_point<std::chrono::high_resolution_clock> startpt;
    float ms;
    long long duration;
    template<typename Func>
    BenchmarkTimer(Func func) : ms(0), duration(0)
    {
        startpt = std::chrono::high_resolution_clock::now();
        func();
        auto endpt = std::chrono::high_resolution_clock::now();
        auto diff = end-start;
        duration = diff.count();
    }
};

void SelectionSort(int Array[])
{
    BenchmarkTimer timer([&]()
    {
        int temp, smallest, position, j;
        for (int i = 0; i < size - 1; i++)
        {
            smallest = Array[i];
            position = i;
            for (j = i + 1; j < size; j++)
                if (Array[j] < smallest)
                {
                    smallest = Array[j];
                    position = j;
                }
            temp = Array[i];
            Array[i] = Array[position];
            Array[position] = temp;
        }
    });
    DisplayArray(Array);
    std::cout << "\nTime taken to sort the array: " << timer.duration << " ms" << std::endl;
}

Другой вариант - добавить еще одну функцию к BenchmarkTimer, которую вы вызываете, когда хотите, чтобы она выполняла вычисления, и переместить туда код деструктора. Будьте осторожны с этим, так как в вашем деструкторе вы объявляете переменную duration, которая скрывает класс duration. Код должен быть что-то вроде

auto endpt = std::chrono::high_resolution_clock::now();
auto init = std::chrono::time_point_cast<std::chrono::milliseconds>(startpt).time_since_epoch().count();
auto final = std::chrono::time_point_cast<std::chrono::milliseconds>(endpt).time_since_epoch().count();
duration = final - init;
// ^ no auto here
...