Я пытаюсь реализовать два класса A и B, которые содержат данные, хранящиеся в контейнере std :: unique_ptr, и A может преобразоваться в B с некоторыми вычислениями. Класс A и класс B показаны ниже. Входной параметр конструктора в классе B предназначен для передачи объекта A. Чтобы измерить производительность во время выполнения, я использую библиотеку std :: chrono и добавляю функцию «print_construction_time» в классе B, чтобы показать время построения.
Процессор: Intel® Core ™ i7-6700HQ 2,6 ГГц
ОЗУ: 16 ГБ
ОС: Windows 10 1909
IDE: сообщество Microsoft Visual Studio 2019 Версия 16.4.4
Настройка оптимизации c / c ++: Максимальная оптимизация (скорость фаворита) (/ O2)
class A
{
public:
A(int input_size, int input_value) // constructor
{
this->data = std::make_unique<int[]>(input_size);
this->size = input_size;
for (int loop_number = 0; loop_number < size; loop_number++) {
data[loop_number] = input_value;
}
}
std::unique_ptr<int[]> get_data()
{
// deep copy
auto return_data = std::make_unique<int[]>(size);
for (int loop_number = 0; loop_number < size; loop_number++) {
return_data[loop_number] = data[loop_number];
}
return return_data;
}
int get_size()
{
return this->size;
}
private:
int size;
std::unique_ptr<int[]> data;
};
class B
{
public:
B(A &input_object) // constructor
{
this->size = input_object.get_size();
this->data = std::make_unique<int[]>(this->size);
this->start = std::chrono::high_resolution_clock::now();
// version 1
for (int loop_number = 0; loop_number < input_object.get_size(); loop_number++) {
this->data[loop_number] = transform_from_A(input_object.get_data()[loop_number]);
}
this->stop = std::chrono::high_resolution_clock::now(); // for execution time measurement
}
std::unique_ptr<int[]> get_data()
{
// deep copy
auto return_data = std::make_unique<int[]>(size);
for (int loop_number = 0; loop_number < size; loop_number++) {
return_data[loop_number] = data[loop_number];
}
return return_data;
}
void print_construction_time()
{
auto duration = std::chrono::duration_cast<std::chrono::microseconds>(stop - start);
std::cout << "Duration: " << duration.count() << "microseconds" << std::endl;
}
private:
int size;
std::unique_ptr<int[]> data;
std::chrono::time_point<std::chrono::steady_clock> start, stop;
int transform_from_A(int input_value)
{
return input_value + 1; // For example
}
};
Основная функция здесь.
int main()
{
A a_object(10000, 6);
B b_object(a_object);
b_object.print_construction_time();
return 0;
}
Для тестирования я запускаю этот код три раза, и время его выполнения составляет 123407us, 112033us и 107586us. Затем я изменяю блок for l oop в конструкторе класса B на версию 2, разработанную с использованием кэшированных данных.
// version 2 <= tremendously faster than version 1
auto data_cached = input_object.get_data();
for (int loop_number = 0; loop_number < input_object.get_size(); loop_number++) {
this->data[loop_number] = transform_from_A(data_cached[loop_number]);
}
Результат измерения версии 2 - 27us, 32us и 43us. Мне любопытно, почему компилятор, по-видимому, не выполняет максимальную оптимизацию по скорости автоматически с помощью уловок кэша, основанных на условии того же результата вычисления, и это должно быть сделано человеком. Я думаю, что такого рода оптимизация может быть осуществлена либо компилятором автоматически, либо с помощью предложения изменения в среде редактора.
Примечание. Я также изменяю настройку оптимизации для тестирования. Производительность во время выполнения схожа между настройкой оптимизации в Максимальной оптимизации (скорость фаворита) (/ O2) и Оптимизацией (скорость фаворита) (/Ox).
Фев. 27. Обновление 2020
Я также пытался изменить тип возвращаемого значения A :: get_data () в классе A, добавив const
ключевое слово std :: unique_ptr.
const std::unique_ptr<int[]> get_data() // <= Add const keyword of std::unique_ptr
{
// deep copy
auto return_data = std::make_unique<int[]>(size);
for (int loop_number = 0; loop_number < size; loop_number++) {
return_data[loop_number] = data[loop_number];
}
return return_data;
}
Результат измерения времени выполнения такой же, как указано выше. Это версии 101486us, 100538us и 120620us в версии 1 и 55us, 30us и 27us в версии 2. Параметр оптимизации - Оптимизация (Скорость фаворита) (/ Ox), а IDE обновлена до версии 16.4.5.
Более того случай «обоих констант» (не только std :: unique_ptr, но и его содержимого), то есть const std::unique_ptr<const int[]>
, также должен быть рассмотрен.
const std::unique_ptr<const int[]> get_data()
{
// deep copy
auto return_data = std::make_unique<int[]>(size);
for (int loop_number = 0; loop_number < size; loop_number++) {
return_data[loop_number] = data[loop_number];
}
return return_data;
}
Результат измерения времени выполнения также аналогичен приведенному выше , Это 114754us, 127327us и 106122us в версии 1 и 32us, 34us и 44us в версии 2. Параметром оптимизации также является Оптимизация (Скорость фаворита) (/Ox).