Объявление переменных за циклом или внутри цикла? - страница 11

 
Vict:

Посмотрел, получается, что модули не допилил ни один компилятор https://en.cppreference.com/w/cpp/compiler_support, так что и смотреть нечего.

Всё же удалось заюзать модули через clang

// module
export module M;
export int f(int x) {
    return 2 + x;
}

// main.cc
import M;
int main() {
        for(int i = 0;  i < 1000000;  ++ i)
                f(5);
}

Скомпилил с оптимизацией, цикл вообще не исполнился (т.е. оптимизация выполняется среди: единица трансляции + полключённые модули, а не как раньше лишь в одной единице трансляции). Безо всякого LTO. std c++ кандидат целиком переехать на модули, имхо, и вопросов не будет: "чего так медленно на этом искусственном примере с голым циклом".

 
Alexey Navoykov:

Так вроде выяснили, что он память каждый раз выделяет и удаляет даже в таком случае:


Кстати я возможно некорректные результаты привёл в прошлый раз.  Это скорее всего было в режиме x86. Сейчас тестю в x64 - результаты по C++ значительно лучше:

1) ~ 2000 мс

2) ~ 200 мс (ускорилось 3 раза)

Правда я ещё Студию обновил до последней версии, видимо это тоже повлияло, т.к. даже x86 сейчас быстрее прошлых замеров.

Ну в общем теперь C++ не так позорно сливает шарпу.  Всего в 3 раза примерно )

Хмм, так нет же гарбадж коллектора, какие вопросы по определении?

я не про скорость, я про память
 
Alexey Navoykov, оказывается в с++20 протащили constexpr string и vector. Т.е. все эти наши тесты вообще не займут ни одной инструкции на обслуживание строки, ну там память выделить и т.д. (ну если символы не из ран тайма приходят конечно). Прикольно.
 
Vict:
Alexey Navoykov, оказывается в с++20 протащили constexpr string и vector. Т.е. все эти наши тесты вообще не займут ни одной инструкции на обслуживание строки, ну там память выделить и т.д. (ну если символы не из ран тайма приходят конечно). Прикольно.

Так для этого необходимо всё явно помечать как constexpr, или он автоматически будет это определять?

Как мне видится, проблема всё ж не в стандарте, а в компиляторе.  Разве ему что-то мешает сейчас вырезать лишнее?  Особенно странно, что шарповский компилятор оптимизирует нормально, а плюсовая версия  от того же самого Майкрософта лажает.  Хотя, казалось бы, база у них должна быть общая (в плане оптимизации таких конструкций)

 
Alexey Navoykov:

Так для этого необходимо всё явно помечать как constexpr, или он автоматически будет это определять?

автоматом, достаточно того, что в строку попадают строки, которые известны во время компиляции. Все операции (поиск, замена, ...) с этим стрингом будут так же во время компиляции (подозреваю, что шарп и мкл считали наши примеры тоже в compile time). В планах сделать все контейнеры constepxr. Т.е. это уже не от настроения компилятора зависит, а гарантированно стандартом, можно параметр шаблона расчитать через парсинг строк, например. Тут вот что интересно - получается, что new/delete теперь тоже constexpr (для constexpr типов)?

Как мне видится, проблема всё ж не в стандарте, а в компиляторе.  Разве ему что-то мешает сейчас вырезать лишнее?  Особенно странно, что шарповский компилятор оптимизирует нормально, а плюсовая версия  от того же самого Майкрософта лажает.  Хотя, казалось бы, база у них должна быть общая (в плане оптимизации таких конструкций)

У плюсов есть недостаток в плане возможностей для оптимизации - она лишь в рамках одной единицы трансляции (если не юзаем LTO). Конечно можно всю std на заголовочных файлах сделать, но не делают (из-за времени компиляции ?). Шарп с модулями в этом плане более продвинут. Но и в с++20 это скоро исправят с появлением модулей. Также в планах перенести туда std (сначала обкатают модули, а потом запилят). Но VS вроде уже сделали std на модулях, можете попробовать (ссылку оставлял выше).

Но я всё равно настаиваю - объявлять лучше за циклом (ну если это не фундаментальный тип).

 
Alexey Navoykov:

Интереса ради решил протестить также в C#.  Мало того, что результаты практически не отличаются между собой по скорости, так ещё и работают на порядок быстрее, чем C++.

Результаты:

Sum: 894782460, Time: 69 ms

Sum: 894782460, Time: 56 ms

А вот аналог в C++:

Sum: 894782460, Time: 2947 ms

Sum: 894782460, Time: 684 ms

Тестирую в VS 2019. Вся оптимизация включена. 

В топку такой C++ )

p.s. Результаты в C# заметно скачут от теста к тесту, но в среднем выходит, что оба варианты одинаковы по скорости.

Подсказка: в шарпе стринг - базовый тип, в плюсах - класс, написанный на плюсах. В варианте на шарпе присваивание строки происходит один раз, в плюсах - 10е6 раз. В итоге плюсы быстрее, но нужно включать думалку при написании кода, а не лепить горбатого а-ля индусы в боинге.
 
SeriousRacoon:
Подсказка: в шарпе стринг - базовый тип, в плюсах - класс, написанный на плюсах. В варианте на шарпе присваивание строки происходит один раз, в плюсах - 10е6 раз. В итоге плюсы быстрее, но нужно включать думалку при написании кода, а не лепить горбатого а-ля индусы в боинге.
Да не, там дело совсем в другом. Я просто подзабыл, что string там является классом, а у них присваивается ссылка, а не сам объект.  Так что сравнение некорректно в таком виде
 

Кстати, по-поводу оптимизации. Хотели ли бы вы, чтобы компилятор вам тут чего-нибудь наоптимизировал?

mutex mtx;

void thread_0() {
        while (true) {
                do_task_0();
                {
                        lock_guard<mutex> lck{mtx};
                        do_task_1();
                }
                do_task_2();
                {
                        lock_guard<mutex> lck{mtx};
                        do_task_3();
                }
                do_task_4();
        {
}
void thread_1() {
        while (true) {
                do_task_5();
                {
                        lock_guard<mutex> lck{mtx};
                        do_task_6();
                }
                do_task_7();
                {
                        lock_guard<mutex> lck{mtx};
                        do_task_8();
                }
                do_task_9();
        {
}
 
Alexey Navoykov:
Да не, там дело совсем в другом. Я просто подзабыл, что string там является классом, а у них присваивается ссылка, а не сам объект.  Так что сравнение некорректно в таком виде
Где присваивается ссылка (указатель)? в плюсовом классе string? вы о чём, там идёт выделение буфера и копирование.
 
SeriousRacoon:
Где присваивается ссылка (указатель)? в плюсовом классе string? вы о чём, там идёт выделение буфера и копирование.

он про шарп

Причина обращения: