Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Measure #FLOP of sqrt() function using PAPI.
/*
* measure_sqrt_flops.cpp
* Copyright (C) 2013 Keisuke Fukuda
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
// icpc -g -Wall -xHOST -O3 -std=c++0x -funroll-loops -finline-functions -ansi-alias -o measure_sqrt_flops measure_sqrt_flops.cpp -lpapi-lrt
#include <cmath>
#include <cstdlib>
#include <iostream>
#include <vector>
#include <papi.h>
#define ERRCODE(ecode) case ecode : err = #ecode; break
#define PAPI_SAFE_CALL(stmt) do { \
int ret = (stmt); \
if (ret != PAPI_OK) { \
const char *err = "(unknown)"; \
switch(ret) { \
ERRCODE(PAPI_EATTR); \
ERRCODE(PAPI_EBUF); \
ERRCODE(PAPI_EBUG); \
ERRCODE(PAPI_ECLOST); \
ERRCODE(PAPI_ECMP); \
/*ERRCODE(PAPI_ESBSTR); same value -4 */ \
ERRCODE(PAPI_ECNFLCT); \
ERRCODE(PAPI_ECOMBO); \
ERRCODE(PAPI_ECOUNT); \
ERRCODE(PAPI_EINVAL); \
ERRCODE(PAPI_EINVAL_DOM); \
ERRCODE(PAPI_EISRUN); \
ERRCODE(PAPI_EMISC); \
ERRCODE(PAPI_ENOCMP); \
ERRCODE(PAPI_ENOCNTR); \
ERRCODE(PAPI_ENOEVNT); \
ERRCODE(PAPI_ENOEVST); \
ERRCODE(PAPI_ENOIMPL); \
ERRCODE(PAPI_ENOINIT); \
ERRCODE(PAPI_ENOMEM); \
ERRCODE(PAPI_ENOSUPP); \
ERRCODE(PAPI_ENOTPRESET); \
ERRCODE(PAPI_ENOTRUN); \
ERRCODE(PAPI_EPERM); \
ERRCODE(PAPI_ESYS); \
} \
fprintf(stderr, \
"%s:%d :[PAPI] %s failed: %s.\n", \
__FILE__, __LINE__, #stmt, err); \
exit(-1); \
} \
} while(0)
const int NUM_LOOP = 1000000;
typedef float real_t;
// typedef double real_t;
template<typename T> inline T sqrtx(T v);
template<> inline float sqrtx<float>(float v) { return sqrtf(v); }
template<> inline double sqrtx<double>(double v) { return sqrt(v); }
int main() {
int ret = PAPI_library_init(PAPI_VER_CURRENT);
if (ret != PAPI_VER_CURRENT) {
fprintf(stderr, "PAPI_library_init() failed.\n");
exit(-1);
}
int ctrs[] = {PAPI_SP_OPS};
int num_events = sizeof(ctrs) / sizeof(ctrs[0]);
int event_set = PAPI_NULL;
PAPI_SAFE_CALL(PAPI_create_eventset(&event_set));
PAPI_SAFE_CALL(PAPI_add_events(event_set, ctrs, num_events));
for (int i = 0; i < 10; i++) {
volatile real_t d = rand() * 1.0/ RAND_MAX;
std::vector<long long> results(num_events, -1L);
// Start measurement
PAPI_SAFE_CALL(PAPI_start(event_set));
{
volatile real_t d = 1.0;
#pragma unroll
for(int i=0; i < NUM_LOOP; i++) {
d += sqrtx(d); // to prevent optimization
}
}
PAPI_SAFE_CALL(PAPI_stop(event_set, results.data()));
double sp_flop = (double)results[0];
sp_flop /= NUM_LOOP;
sp_flop -= 1; // substract 1 FLOP for minus op.
std::cout << "SP flop of sqrt() : " << sp_flop << std::endl;
}
PAPI_SAFE_CALL(PAPI_cleanup_eventset(event_set));
PAPI_SAFE_CALL(PAPI_destroy_eventset(&event_set));
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment