Разница во времени выполнения в C и C++

Недавно я нашел этот сайт под названием codechef, где вы можете отправлять решения проблем. Я представил два ответа на вопрос, один на C, а другой на C++. Оба кода практически одинаковы. Но когда код, который я отправил на C, был выполнен за 4,89 секунды, время ожидания кода, который я отправил на C++, истекло (более 8 секунд). Как это возможно? Куда уходит время?

Вопрос был:

Вход

Ввод начинается с двух положительных целых чисел n k (n, k‹=107). Следующие n строк ввода содержат по одному положительному целому числу ti, не превышающему 10^9, каждая.

Выход

Выведите одно целое число, обозначающее, сколько целых чисел ti делятся на k.

Example

Input:
7 3
1
51
966369
7
9
999996
11

Output:
4

Мой код на С:

 #include<stdio.h>
   
 int main()  {
   
   int n,k,t;
   scanf("%d %d",&n,&k);
   int i,num=0;
   for(i=0;i<n;i++)  {
     scanf("%d",&t);
     if(t%k==0)  num++;
   }     
   
   printf("%d",num);
    
   return 0;
 }

Мой код на С++:

 #include<iostream>
  
 using namespace std;
   
 int main()  {
  
   int n, k, t,num=0;
   cin>>n>>k;
   for(int i=0;i<n;i++)  {
     cin>>t;
     if(t%k==0)  num++;
   }
  
   cout<<num;
   return 0;
 } 

person arry36    schedule 06.03.2014    source источник
comment
Извини! Это было 10^9. Ошибка копирования-вставки. :)   -  person arry36    schedule 06.03.2014
comment
Прежде всего попробуйте C++ с cstdio.   -  person jacekmigacz    schedule 06.03.2014
comment
@ any36 - Значит, ваше время включало то, как быстро кто-то может вводить ввод?? Я вижу вызовы scanf() в коде C и cin в коде C++. Включено ли это в тест времени?   -  person PaulMcKenzie    schedule 06.03.2014
comment
@PaulMcKenzie: сайт тестирует код с предустановленными случаями. Так что, я думаю, ввод текста не займет много времени.   -  person arry36    schedule 06.03.2014
comment
@ any36 - Значит, вы не уверены, что они делают с вводом-выводом. Если это так, то, на мой взгляд, тайминги ошибочны. Я мог бы видеть, измеряете ли вы время кода без ввода-вывода или даже время, необходимое для чтения и обработки большого файла, но даже это требует многих тестовых прогонов, чтобы объединиться вокруг надежного результата.   -  person PaulMcKenzie    schedule 06.03.2014
comment
Вы используете разные вызовы ввода-вывода? Можно ли использовать одинаковые вызовы и посмотреть, похожи ли они? Если да, то это действительно cin/out против scanf/printf. По крайней мере, вы можете просто скомпилировать код C с помощью компилятора Cpp и посмотреть, как это работает.   -  person aks    schedule 06.03.2014
comment
@PaulMcKenzie — из часто задаваемых вопросов Codechef: Codechef может тестировать ваш код несколько раз с разными входными файлами. Ваша программа должна прочитать, обработать и вывести результат для входного файла в течение заданного срока. Если ваш код дает правильный ответ в течение установленного времени для каждого входного файла, отображаемое время выполнения представляет собой общее время, затраченное на каждый тестовый пример.   -  person arry36    schedule 06.03.2014
comment
@aks: Да, я переписал код C++, используя scanf и printf, и на самом деле это заняло на 0,2 с меньше, чем код на C.   -  person arry36    schedule 06.03.2014


Ответы (2)


Код на самом деле не одинаков, хотя они делают одно и то же.

Версия c++ использует cin и потоки, которые по умолчанию медленнее, чем scanf и т.д.

По умолчанию cin/cout тратят время на синхронизацию с буферами stdio библиотеки C, так что вы можете свободно смешивать вызовы scanf/printf с операциями над cin/cout. Вы можете отключить это с помощью std::ios_base::sync_with_stdio(false);

При этом время, затрачиваемое на это, будет более или менее аналогичным, как я ожидаю

person const_ref    schedule 06.03.2014
comment
+1 за указание sync_with_stdio вместо классного iostreams are slow, что просто неправильно. - person Sebastian Mach; 06.03.2014
comment
Я добавил sync_with_stdio, и теперь код работает за 4,78 с. :) - person arry36; 06.03.2014
comment
@ arry36 Как я и думал ;) - person const_ref; 06.03.2014
comment
Является ли хорошей практикой программирования замену всех cin/cout на scanf/printf в cpp? - person arry36; 06.03.2014
comment
@arry36 arry36 Из соображений безопасности типов я придерживаюсь использования потоков, но другие люди, которых я знаю, делают это. Однако на вашем месте я бы не стал, С++ должен быть написан как С++ imo;) - person const_ref; 06.03.2014
comment
без явной установки std::ios_base::sync_with_stdio(false) он не только синхронизируется с stdio C, но также является потокобезопасным, что c не гарантирует afaik и требует дополнительного времени. - person user1942027; 06.03.2014
comment
ТАК, что «sync_with_stdio» позволяет потокам работать независимо друг от друга. Но в чем компромисс? - person arry36; 06.03.2014
comment
Компромисс заключается в том, что потоки C++ больше не синхронизируются со стандартными потоками C после каждой операции ввода/вывода, поэтому в идеале вам нужно выбрать либо/или, а не смешивать оба. - person const_ref; 06.03.2014
comment
О, если синхронизация включена, можно смешивать scanf и cin и буфер всегда синхронизируется? Извините за беспокойство. Я просто не понимаю, что синхронизируется. - person arry36; 06.03.2014
comment
Да. Подробнее см. здесь: en.cppreference.com/w/cpp/io/ ios_base/sync_with_stdio - person const_ref; 06.03.2014
comment
Ой! Я получаю это сейчас. Все потоки в C++ постоянно синхронизируются. Вот почему использование потоков занимает больше времени. Большое спасибо! :) - person arry36; 06.03.2014

Я обычно добавляю эти 3 строки в свой код сразу после main() для более быстрого ввода-вывода:

ios_base::sync_with_stdio(false);

cin.tie(NULL);

cout.tie(NULL);

Итак, попробуйте это:

int main()  
{
   ios_base::sync_with_stdio(false);
   cin.tie(NULL);
   cout.tie(NULL);
   int n, k, t,num=0;
   cin>>n>>k;
   for(int i=0;i<n;i++)  {
     cin>>t;
     if(t%k==0)  num++;
   }

   cout<<num;
   return 0;
 } 
person Vishal Srivastav    schedule 24.03.2019