Огромная разница в скорости между одинаковыми программами c и c++

Я очень новичок в программировании на c и c++, поэтому я начну с основ. Я написал идентичные программы цикла Фибоначчи для c и c++ для проверки относительной скорости. Я думал, что они будут примерно одинаковыми для чего-то такого простого, но версия c++ медленнее в 60 раз. Все, что они делают, это перебирают и выводят первые 14 чисел Фибоначчи 10000 раз. Вот версия c:

#include <stdio.h>

int main (){
    int c = 0;
    int x, y, z;

    while(c < 10000)
    {
        x = 0;
        y = 1;
        while(x < 255)
        {
            printf("%d\n", x);
            z = x + y;
            x = y;
            y = z;
        }
        c++;
    }
    return 0;
}

а вот версия c++:

#include <iostream>
using namespace std;

int main()
{
    int c = 0, x = 0, y = 0, z = 0;
    while(c < 10000)
    {
        x = 0;
        y = 1;
        while(x < 255)
        {
            cout << x << endl;
            z = x + y;
            x = y;
            y = z;
        }
        c++;
    }
    return 0;
}

Я написал оба в notepad++ и скомпилировал их, используя g++ из mingw, который поставляется с кодовыми блоками:

g++ -o fibc.exe fib.c -s
g++ -o fibcpp.exe fib.cpp -s

Размер исполняемых файлов очень разный: размер c равен 8,5 КБ, а размер c++ равен 784 КБ! Я использовал PowerShell для определения времени их:

Measure-Command {start-process "C:\Path\fibcpp.exe" -RedirectStandardOutput "C:\Path\cpp.txt" -Wait}

Полученные файлы идентичны, но версия c заняла 1 секунду, а версия c++ - 60 секунд! (На самом деле, создание цикла в 1 миллион для программы c заняло всего 13 секунд). Я также написал c++ в Visual Studio 17 и скомпилировал его с конфигурацией выпуска x86. Размер программы теперь составляет 9,5 КБ, но время выполнения совпадает с версией g++: 62 секунды. Почему это происходит для такой простой программы?

Ответы

Ответ 1

Вы сравниваете printf с cout, так как это основные узкие места в вашей программе.

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

Если вы действительно хотите сравнить два языка, удалите функции печати и замените их фиктивной функцией "foo" с внешней связью:

void foo (int x);
...

while(x < 255)
{
  foo(x);

При сравнении этого кода с gcc -O3 для x86 я получаю практически идентичный код для версии C и C++ версии.

Единственное заметное отличие - это "CRT" goo, который C++ добавил в конце main(). Это вызов atexit и другой очистки, которую C тоже сделает, но, возможно, за пределами кода приложения. Тем не менее, в C++ всегда будут накладные расходы, поскольку он должен вызывать конструкции и очищать деструкторы объектов со статической продолжительностью хранения. С не должен этого делать.

Ответ 2

Причина, по которой C++ cout работает медленно, объясняется в здесь.

По умолчанию объекты iostream и потоки cstdio синхронизируются (как если бы эта функция была вызвана с аргументом true в качестве аргумента).

Поэтому по умолчанию cout синхронизируется со stdio.

Попробуйте выполнить следующее для ускорения.

ios_base::sync_with_stdio(false)

Но будьте осторожны, этот код напечатает то, чего вы не ожидаете.

#include <iostream>
#include <cstdio>

int main()
{
    std::ios::sync_with_stdio(false);
    std::cout << "a\n";
    std::printf("b\n");
    std::cout << "c\n";
}