LINUX.ORG.RU

C vs C++


0

0

---begin test.c---
main()
{
int i;
for(i=0;i<100000;i++)
{

}
}
end test.c---

#gcc test.c
#time a.out
eal 0m0.002s
user 0m0.000s
sys 0m0.000s
#c++ test.c
#time a.out
real 0m0.006s
user 0m0.010s
sys 0m0.000s

Вывод?
Это надо понимать что код на С в 3 раза быстрее кода на С++
--
Nick

anonymous

Учите мат. статистику, милейший. Это надо понимать так, что результаты измерений равны с точностью до погрешности измерения.

anonymous
()

Прокомментируйте это: :))))


$cat time_c.c
#include<stdlib.h>

int compare(const void* arg1, const void *arg2){
const long* a1 = (const long*)arg1;
const long* a2 = (const long*)arg2;
return (*a1) - (*a2);
}

#define SIZE 1000000

long data[SIZE];

int main(){
long i;
for(i = 0; i < SIZE; i++) data[i] = rand();
qsort(data,SIZE,sizeof(long),compare);
}

$time ./time_c
0.55user 0.02system 0:00.56elapsed 100%CPU (0avgtext+0avgdata 0maxresident)k
0inputs+0outputs (104major+1973minor)pagefaults 0swaps

$cat time_cc.cpp
#include <cstdlib>
#include <algorithm>
using namespace std;

#define SIZE 1000000

long data[SIZE];

int main(){
for(long i = 0; i < SIZE; i++) data[i] = rand();
sort(data,data+SIZE);
}

$time ./time_cc
0.41user 0.01system 0:00.42elapsed 99%CPU (0avgtext+0avgdata 0maxresident)k
0inputs+0outputs (174major+1002minor)pagefaults 0swaps

Итого: На С++ программа меньше, читабельней и работает быстрее :-)

anonymous
()

тогда-уж STLным сортом сортировать, побыстрей будет да и корректнее.

anonymous
()

тьфу, прогнал, беру замечание про STLный сорт взад :)

anonymous
()

Сравнение нечестное. C++ темплейты нужно сравнивать с макросами (а не с библиотечными функциями) Си.

anonymous
()

Дык, кто мешает привести примен на сортировку с помощью макросов? Ну-ка, ну-ка... Насильники - милости просим!

anonymous
()

Все дело в кастинге, который является известным тормозом в С. Можно попробовать, ради спортивного интереса, убрать кастинг из функции compare и вычитать адреса друг из друга. И тогда станет ясно, где тормозит. Кстати, пробовал ли кто icc (Intel C Compiler) на этот предмет?

agat
()

agat, про "известного тормоза" сам придумал? Только что? Иди и не позорься.

Главная причина торможения - косвенный вызов функции сравнения, которой аргументы передаются через стек. Если взять код qsort из glibc, убрать из него вызовы функции сравнения (заменить на операции), то программа на Си станет работать примерно в 3 раза быстрее, чем программа на темплейтах Си++. Если угодно, могу запостить текст программы и тестовые результаты.

anonymous
()

> for(long i = 0; i < SIZE; i++) data[i] = rand();

Ты и С++ не знаешь.

Должно быть:

generate(data, data + SIZE, rand);

;)

anonymous
()

to anonymous (*) (2003-05-10 01:45:59.692)

что это за "косвеный" вызов такой - функцию или вызывают или нет, а аргументы в функцию всегда через стек передаются. А то что операция быстрее, чем вызов функции, это и без экспериментов ясно. А насчет кастинга зря твои сомненья ;)

agat
()

> что это за "косвеный" вызов такой

Через указатель. (разница в общем-то несущественная, но заинлайнить такой вызов невозможно)

> а аргументы в функцию всегда через стек передаются

Ну можно через регистры.

> А то что операция быстрее, чем вызов функции,

Да? Операция new намного быстрее функции malloc? ;)

> А насчет кастинга зря твои сомненья

А ты расскажи про "кастинг" в Си, какой он дорогой и нехороший ;)

не anonymous (*) (2003-05-10 01:45:59.692)

anonymous
()

agat, кастинг одного указательного типа к другому указательному типу вообще не приводит к появлению новых машинных инструкций. Если Вы в этом сомневаетесь, проверяйте.

Смотрите сами: операция a[i] < a[j] в идеале генерируется в две инструкции x86. Сравните с косвенным вызовом функции сравнения, для которой нужно
1) получить адреса сравниваемых значений (2 инструкции);
2) сохранить их в стеке (2 инструкции);
3) загрузить значение адреса функции на регистр, вызвать по загруженному адресу, выполнить действия в прологе функции (4 инструкции да еще невозможность предсказания перехода, то есть сброс конвейера);
4) загрузить адреса сравниваемых элементов из стека на регистры (2 инструкции)
5) вычесть одно из другого (1);
6) эпилог функции (2);
7) сравнение возвращённого значения с нулём (1).

Получилось 14 инструкций против 2.

anonymous
()

про кастинг я конечно прогнал, тем более что речь идет об указателях (адрес всегда одинаков). соррри... Просто на памяти лекции по ассемблеру, где делали преобразования Сишных типов, ну дык типов, а не адресов! Еще раз, сорри - прогнал, прогнал :)

agat
()

Ну и? Выводы-то какие?
- Кто-то предлагает переписывать qsort только ради того, чтобы в одном тесте сделать С++. А что на счет всех остальных случаев использования std::sort? Под это тоже можно при случае переписать код qsort...
А темплейты из С++ тем и удобны, что не нужно гемороиться при каждом новом случае.
Ну а если есть что-то полезное и написанное на С, то из С++ это также можно вызвать.
В то же время, из С сложно пользоваться С++-ными плюшками (да той же STL!)

anonymous
()

> Ну и? Выводы-то какие?

Тест дебильный - массив int сортировать.

> - Кто-то предлагает переписывать qsort только ради того, чтобы в одном тесте сделать С++.

Ради одного int можно и переписать.

> А что на счет всех остальных случаев использования std::sort? Под это тоже можно при случае переписать код qsort...

А ты приведи бенчмарки для остальных случаев. Например, отсортируй массив структур

struct { char name[64]; int eto_uzhe_ne_vazno; };

по полю name в алфавитном порядке без учета регистра. (В C++ можешь пользоваться string если хочешь ;) ).

> А темплейты из С++ тем и удобны, что не нужно гемороиться при каждом новом случае.

Кто ищет, тот найдет.

> Ну а если есть что-то полезное и написанное на С, то из С++ это также можно вызвать.

Например longjmp? Или goto в середину блока? Сигналы месте с исключениями? И, наконец, деструкторы и fork?

> В то же время, из С сложно пользоваться С++-ными плюшками (да той же STL!)

А нужно?

anonymous
()

> кастинг одного указательного типа к другому указательному типу > вообще не приводит к появлению новых машинных инструкций. > Если Вы в этом сомневаетесь, проверяйте.

ну Вы конечно имели в виду только указатели на plain ol data.. иначе это не верно -- от производного к базовому например..

dilmah ★★★★★
()

по поводу СТЛ -- больше всего меня выводит из себя. Просто это аксиома, если хотеть использовать обобщенное программирование то оно должно пронизывать всю программу. Если начать просто штамповать аргументы входных функций std::vector< int > вместо int *, то это ни к чему хорошему не приведет. А ведь штампуют.

dilmah ★★★★★
()

2dilmah: высказывание о кастинге относилось только к Си.

> Ну и? Выводы-то какие?

А такие, что и Си и Си++ каждый имеют свою сферу применения, и говорить о том, что Си++ однозначно лучше Си неправильно. Как и наоборот.

Использование STL приводит к тому, что программа получается на вид проще и понятнее, но сильно теряет в производительности против макросов и тонко настроенного кода.

anonymous
()

Дык! Однако, не я первый начал. И первый тест был еще более идиотский. Надо ж было этому насильнику ответить :))) Ничего против С как языка не имею, но привык уже писать на С++, к тому же удобство разработки определяется не столько самим языком, сколько наличием уже готовых компонентов и инструментальных средств. Под С++ их уже столько, что с этим как ни верти приходится считаться...

anonymous
()

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

Тогда самым удобным языком является perl (CPAN). Но, согласен, тест с циклом был ...

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.