Ниже приведен код, который я профилирую:
#include <iostream>
#include <fstream>
#define N 10000
using namespace std;
int main()
{
ofstream fout;
fout.open("log.txt");
int A[N], B[N], C[N];
for(int i=0; i<N; i++)
{
A[i] = B[i] = i;
}
int sum = 0;
for(int j=0; j<N; j++)
{
C[j] = A[j]+B[j];
//fout<<C[j]<<endl;
sum += C[j];
sum %= 103;
}
cout<<sum<<endl;
return 0;
}
Ниже приведена команда профилирования:
perf stat -e instructions:u -e instructions:k -e cache-misses -e page-faults -e branch-misses ./test
Выход:
Performance counter stats for './test':
15,60,186 instructions:u
8,35,753 instructions:k
24,345 cache-misses
123 page-faults
13,051 branch-misses
0.001327182 seconds time elapsed
Однако, когда я раскомментирую эту единственную закомментированную строку, я получаю следующий вывод:
Performance counter stats for './test':
75,72,868 instructions:u
12,29,31,625 instructions:k
2,18,333 cache-misses
121 page-faults
73,662 branch-misses
0.525844017 seconds time elapsed
Я не могу понять, что является причиной такого огромного увеличения числа пропусков в кэш-памяти и умеренно высокого увеличения числа пропусков в ветвях. Любые идеи будут оценены!
Без «fout<<C[j]<<endl;
«Линия, ваша программа в основном работает в пространстве пользователя (я бы сказал, значительная часть вашей программы полностью работает в пространстве пользователя). Раскомментировав эту строку (которая находится внутри цикла), вы вводите много дополнительных системных вызовов (это видно из огромного увеличения instructions:k
номер, сообщенный профилировщиком). Системные вызовы дороги, поскольку они включают переключение контекста, которое, в зависимости от архитектуры оборудования и ОС, может сделать недействительной заметную часть кэша ЦП.
Обратите внимание, что главный виновник здесь endl
(что вызывает очистку буферов и, таким образом, запускает системный вызов). Замени это '\n'
и влияние на производительность должно быть намного меньше.
Других решений пока нет …