Считать инструкции с плавающей точкой

Я пытаюсь посчитать количество операций с плавающей запятой в одной из моих программ, и я думаю, perf может быть инструмент, который я ищу (есть ли альтернативы?), но у меня есть проблемы с ограничением его до определенной функции / блока кода. Давайте возьмем следующий пример:

#include <complex>
#include <cstdlib>
#include <iostream>
#include <type_traits>

template <typename T>
typename std::enable_if<std::is_floating_point<T>::value, T>::type myrand()
{
return static_cast <T> (std::rand()) / static_cast <T> (RAND_MAX);
}

template <typename T>
typename std::enable_if<!std::is_floating_point<T>::value, std::complex<typename T::value_type>>::type myrand()
{
typedef typename T::value_type S;

return std::complex<S>(
static_cast <S> (std::rand()) / static_cast <S> (RAND_MAX),
static_cast <S> (std::rand()) / static_cast <S> (RAND_MAX)
);
}

int main()
{
auto const a = myrand<Type>();
auto const b = myrand<Type>();

// count here
auto const c = a * b;
// stop counting here

// prevent compiler from optimizing away c
std::cout << c << "\n";

return 0;
}

myrand() Функция просто возвращает случайное число, если тип T является комплексным, то случайное комплексное число. Я не жестко запрограммировал дубликаты в программе, потому что они были бы оптимизированы компилятором.

Вы можете скомпилировать файл (давайте назовем его bench.cpp) с c++ -std=c++0x -DType=double bench.cpp,

Теперь я хотел бы подсчитать количество операций с плавающей запятой, которые можно выполнить на моем процессоре (архитектура Nehalem, x86_64, где с плавающей запятой выполняется с помощью скалярного SSE) с событием r8010 (см. руководство Intel 3B, раздел 19.5). Это может быть сделано с

perf stat -e r8010 ./a.out

и работает как положено; однако он считает общее количество мопов (есть ли таблица, показывающая, сколько моп movsd например является?) а также Меня интересует только число для умножения (см. пример выше).

Как это может быть сделано?

2

Решение

Я наконец нашел способ сделать это, хотя не используя perf но вместо соответствующего перф API. Сначала нужно определить perf_event_open функция, которая на самом деле является системным вызовом:

#include <cstdlib> // stdlib.h for C
#include <cstdio> // stdio.h for C
#include <cstring> // string.h for C
#include <unistd.h>
#include <sys/ioctl.h>
#include <linux/perf_event.h>
#include <asm/unistd.h>

long perf_event_open(
perf_event_attr* hw_event,
pid_t pid,
int cpu,
int group_fd,
unsigned long flags
) {
int ret = syscall(__NR_perf_event_open, hw_event, pid, cpu, group_fd, flags);
return ret;
}

Далее выбираются события, которые нужно посчитать:

perf_event_attr attr;

// select what we want to count
std::memset(&attr, 0, sizeof(perf_event_attr));
attr.size = sizeof(perf_event_attr);
attr.type = PERF_TYPE_HARDWARE;
attr.config = PERF_COUNT_HW_INSTRUCTIONS;
attr.disabled = 1;
attr.exclude_kernel = 1; // do not count the instruction the kernel executes
attr.exclude_hv = 1;

// open a file descriptor
int fd = perf_event_open(&attr, 0, -1, -1, 0);

if (fd == -1)
{
// handle error
}

В этом случае я хочу просто посчитать количество инструкций. Инструкции с плавающей точкой можно посчитать на моем процессоре (Nehalem), заменив соответствующие строки на

attr.type = PERF_TYPE_RAW;
attr.config = 0x8010; // Event Number = 10H, Umask Value = 80H

Установив тип в RAW, можно практически посчитать каждое событие, которое предлагает процессор; число 0x8010 указывает, какой. Обратите внимание, что это число сильно зависит от процессора! Правильные числа можно найти в Руководстве Intel 3B, часть 2, глава 19, выбрав правильный подраздел.

Затем можно измерить код, заключив его в

// reset and enable the counter
ioctl(fd, PERF_EVENT_IOC_RESET, 0);
ioctl(fd, PERF_EVENT_IOC_ENABLE, 0);

// perform computation that should be measured here

// disable and read out the counter
ioctl(fd, PERF_EVENT_IOC_DISABLE, 0);
long long count;
read(fd, &count, sizeof(long long));
// count now has the (approximated) result

// close the file descriptor
close(fd);
2

Другие решения


По вопросам рекламы [email protected]