|
Packit |
577717 |
|
|
Packit |
577717 |
/****************************/
|
|
Packit |
577717 |
/* THIS IS OPEN SOURCE CODE */
|
|
Packit |
577717 |
/****************************/
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/**
|
|
Packit |
577717 |
* @file: PAPI_Matlab.c
|
|
Packit |
577717 |
* CVS: $Id$
|
|
Packit |
577717 |
* @author Joseph Thomas <jthomas@cs.utk.edu>
|
|
Packit |
577717 |
*
|
|
Packit |
577717 |
* @brief PAPI Matlab integration.
|
|
Packit |
577717 |
* See PAPI_Matlab.readme for more information.
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
#include "mex.h"
|
|
Packit |
577717 |
#include "matrix.h"
|
|
Packit |
577717 |
#include "papi.h"
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static long long accum_error = 0;
|
|
Packit |
577717 |
static long long start_time = 0;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
void mexFunction(int nlhs, mxArray *plhs[],
|
|
Packit |
577717 |
int nrhs, const mxArray *prhs[]) {
|
|
Packit |
577717 |
float real_time, proc_time, rate;
|
|
Packit |
577717 |
int i;
|
|
Packit |
577717 |
int number_of_counters;
|
|
Packit |
577717 |
unsigned int mrows, nchars;
|
|
Packit |
577717 |
unsigned int *events;
|
|
Packit |
577717 |
unsigned int flop_events[2];
|
|
Packit |
577717 |
long long ins = 0, *values, flop_values[2];
|
|
Packit |
577717 |
long long elapsed_time;
|
|
Packit |
577717 |
int result;
|
|
Packit |
577717 |
char *input, *temp;
|
|
Packit |
577717 |
char one_output[] = "This function produces one output per running counter.";
|
|
Packit |
577717 |
char no_input[] = "This function expects no input.";
|
|
Packit |
577717 |
char error_reading[] = "Error reading the running counters.";
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* Check for proper number of arguments. */
|
|
Packit |
577717 |
if(nrhs < 1) {
|
|
Packit |
577717 |
mexErrMsgTxt("This function expects input.");
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
nchars = mxGetNumberOfElements(prhs[0]);
|
|
Packit |
577717 |
input = (char *)mxCalloc(nchars, sizeof(char) + 1);
|
|
Packit |
577717 |
input = mxArrayToString(prhs[0]);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if(!strncmp(input, "num", 3)) {
|
|
Packit |
577717 |
if(nrhs != 1) {
|
|
Packit |
577717 |
mexErrMsgTxt(no_input);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
else if(nlhs != 1) {
|
|
Packit |
577717 |
mexErrMsgTxt("This function produces one and only one output: counters.");
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
result = PAPI_num_counters();
|
|
Packit |
577717 |
if(result < PAPI_OK) {
|
|
Packit |
577717 |
mexPrintf("Error code: %d\n", result);
|
|
Packit |
577717 |
mexErrMsgTxt("Error reading counters.");
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
plhs[0] = mxCreateDoubleScalar((double)result);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
else if((!strncmp(input, "flip", 4)) || (!strncmp(input, "flop", 4))) {
|
|
Packit |
577717 |
if(nrhs != 1) {
|
|
Packit |
577717 |
mexErrMsgTxt(no_input);
|
|
Packit |
577717 |
} else if(nlhs > 2) {
|
|
Packit |
577717 |
if (input[2] == 'i')
|
|
Packit |
577717 |
mexErrMsgTxt("This function produces 1 or 2 outputs: [ops, mflips].");
|
|
Packit |
577717 |
else
|
|
Packit |
577717 |
mexErrMsgTxt("This function produces 1 or 2 outputs: [ops, mflops].");
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
if (input[2] == 'i') {
|
|
Packit |
577717 |
if(result = PAPI_flips( &real_time, &proc_time, &ins, &rate)
|
|
Packit |
577717 |
mexPrintf("Error code: %d\n", result);
|
|
Packit |
577717 |
mexErrMsgTxt("Error getting flips.");
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
} else {
|
|
Packit |
577717 |
if(result = PAPI_event_name_to_code("EMON_SSE_SSE2_COMP_INST_RETIRED_PACKED_DOUBLE", &(flop_events[0])) < PAPI_OK) {
|
|
Packit |
577717 |
if(result = PAPI_flops( &real_time, &proc_time, &ins, &rate)
|
|
Packit |
577717 |
mexPrintf("Error code: %d\n", result);
|
|
Packit |
577717 |
mexErrMsgTxt("Error getting flops.");
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
} else {
|
|
Packit |
577717 |
if(start_time == 0) {
|
|
Packit |
577717 |
flop_events[1] = PAPI_FP_OPS;
|
|
Packit |
577717 |
start_time = PAPI_get_real_usec();
|
|
Packit |
577717 |
if((result = PAPI_start_counters(flop_events, 2)) < PAPI_OK) {
|
|
Packit |
577717 |
mexPrintf("Error code: %d\n", result);
|
|
Packit |
577717 |
mexErrMsgTxt("Error getting flops.");
|
|
Packit |
577717 |
} else {
|
|
Packit |
577717 |
ins = 0;
|
|
Packit |
577717 |
rate = 0;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
} else {
|
|
Packit |
577717 |
if((result = PAPI_read_counters(flop_values, 2)) < PAPI_OK) {
|
|
Packit |
577717 |
mexPrintf("%d\n", result);
|
|
Packit |
577717 |
mexErrMsgTxt(error_reading);
|
|
Packit |
577717 |
} else {
|
|
Packit |
577717 |
elapsed_time = PAPI_get_real_usec() - start_time;
|
|
Packit |
577717 |
ins = (2*flop_values[0])+flop_values[1];
|
|
Packit |
577717 |
rate = ((float)ins)/((float)elapsed_time);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
if(nlhs > 0) {
|
|
Packit |
577717 |
plhs[0] = mxCreateDoubleScalar((double)(ins - accum_error));
|
|
Packit |
577717 |
/* this call adds 7 fp instructions to the total */
|
|
Packit |
577717 |
/* but apparently not on Pentium M with Matlab 7.0.4 */
|
|
Packit |
577717 |
/* accum_error += 7; */
|
|
Packit |
577717 |
if(nlhs == 2) {
|
|
Packit |
577717 |
plhs[1] = mxCreateDoubleScalar((double)rate);
|
|
Packit |
577717 |
/* the second call adds 4 fp instructions to the total */
|
|
Packit |
577717 |
/* but apparently not on Pentium M with Matlab 7.0.4 */
|
|
Packit |
577717 |
/* accum_error += 4; */
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
else if(!strncmp(input, "start", 5)) {
|
|
Packit |
577717 |
if(nlhs != 0) {
|
|
Packit |
577717 |
mexErrMsgTxt("This function produces no output.");
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
if(nrhs > (PAPI_num_counters() + 1)) {
|
|
Packit |
577717 |
mexErrMsgTxt(one_output);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
mrows = mxGetM(prhs[1]);
|
|
Packit |
577717 |
events = (unsigned int *)mxCalloc(nrhs - 1, sizeof(int) + 1);
|
|
Packit |
577717 |
for(i = 1; i < nrhs; i++) {
|
|
Packit |
577717 |
if(mxIsComplex(prhs[i]) || !(mrows == 1) ) {
|
|
Packit |
577717 |
mexErrMsgTxt("Input must be a list of strings.");
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
if(mxIsChar(prhs[i])) {
|
|
Packit |
577717 |
nchars = mxGetNumberOfElements(prhs[i]);
|
|
Packit |
577717 |
temp = (char *)mxCalloc(nchars, sizeof(char) + 1);
|
|
Packit |
577717 |
temp = mxArrayToString(prhs[i]);
|
|
Packit |
577717 |
if(result = PAPI_event_name_to_code(temp, &(events[i - 1])) < PAPI_OK) {
|
|
Packit |
577717 |
mxFree(temp);
|
|
Packit |
577717 |
mexPrintf("Error code: %d\n", result);
|
|
Packit |
577717 |
mexErrMsgTxt("Incorrect PAPI code given.");
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
mxFree(temp);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
else {
|
|
Packit |
577717 |
events[i - 1] = (unsigned int)mxGetScalar(prhs[i]);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
if((result = PAPI_start_counters(events, nrhs - 1)) < PAPI_OK) {
|
|
Packit |
577717 |
mxFree(events);
|
|
Packit |
577717 |
mexPrintf("Error code: %d\n", result);
|
|
Packit |
577717 |
mexErrMsgTxt("Error initializing counters.");
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
mxFree(events);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
else if(!strncmp(input, "stop", 4)) {
|
|
Packit |
577717 |
if(nrhs != 1) {
|
|
Packit |
577717 |
mexErrMsgTxt(no_input);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
number_of_counters = PAPI_num_counters();
|
|
Packit |
577717 |
if(nlhs > number_of_counters ) {
|
|
Packit |
577717 |
mexErrMsgTxt(one_output);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
if (nlhs == 0)
|
|
Packit |
577717 |
values = (long long*)mxCalloc(number_of_counters, sizeof(long long));
|
|
Packit |
577717 |
else
|
|
Packit |
577717 |
values = (long long *)mxCalloc(nlhs, sizeof(long long) + 1);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (start_time == 0) {
|
|
Packit |
577717 |
if (nlhs == 0)
|
|
Packit |
577717 |
result = PAPI_stop_counters(values, number_of_counters);
|
|
Packit |
577717 |
else
|
|
Packit |
577717 |
result = PAPI_stop_counters(values, nlhs);
|
|
Packit |
577717 |
} else {
|
|
Packit |
577717 |
start_time = 0;
|
|
Packit |
577717 |
result = PAPI_stop_counters(flop_values, 2);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if(result < PAPI_OK) {
|
|
Packit |
577717 |
if(result != PAPI_ENOTRUN) {
|
|
Packit |
577717 |
mexPrintf("Error code: %d\n", result);
|
|
Packit |
577717 |
mexErrMsgTxt("Error stopping the running counters.");
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
accum_error = 0;
|
|
Packit |
577717 |
for(i = 0; i < nlhs; i++) {
|
|
Packit |
577717 |
plhs[i] = mxCreateDoubleScalar((double)values[i]);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
mxFree(values);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
else if(!strncmp(input, "read", 4)) {
|
|
Packit |
577717 |
if(nrhs != 1) {
|
|
Packit |
577717 |
mexErrMsgTxt(no_input);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
if(nlhs > PAPI_num_counters()) {
|
|
Packit |
577717 |
mexErrMsgTxt(one_output);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
values = (long long *)mxCalloc(nlhs, sizeof(long long) + 1);
|
|
Packit |
577717 |
if((result = PAPI_read_counters(values, nlhs)) < PAPI_OK) {
|
|
Packit |
577717 |
mexPrintf("%d\n", result);
|
|
Packit |
577717 |
mexErrMsgTxt(error_reading);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
for(i = 0; i < nlhs; i++) {
|
|
Packit |
577717 |
plhs[i] = mxCreateDoubleScalar((double)values[i]);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
mxFree(values);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
else if(!strncmp(input, "accum", 5)) {
|
|
Packit |
577717 |
if(nrhs > PAPI_num_counters() + 1) {
|
|
Packit |
577717 |
mexErrMsgTxt(no_input);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
if(nlhs > PAPI_num_counters()) {
|
|
Packit |
577717 |
mexErrMsgTxt(one_output);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
values = (long long *)mxCalloc(nlhs, sizeof(long long) + 1);
|
|
Packit |
577717 |
for(i = 0; i < nrhs - 1; i++) {
|
|
Packit |
577717 |
values[i] = (long long)(*(mxGetPr(prhs[i + 1])));
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
if(result = PAPI_accum_counters(values, nlhs) < PAPI_OK) {
|
|
Packit |
577717 |
mexPrintf("Error code: %d\n", result);
|
|
Packit |
577717 |
mexErrMsgTxt(error_reading);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
for(i = 0; i < nlhs; i++) {
|
|
Packit |
577717 |
plhs[i] = mxCreateDoubleScalar((double)values[i]);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
mxFree(values);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
else if(!strncmp(input, "ipc", 3)) {
|
|
Packit |
577717 |
if(nrhs != 1) {
|
|
Packit |
577717 |
mexErrMsgTxt(no_input);
|
|
Packit |
577717 |
} else if(nlhs > 2) {
|
|
Packit |
577717 |
mexErrMsgTxt("This function produces 1 or 2 outputs: [ops, ipc].");
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
if(PAPI_ipc(&real_time, &proc_time, &ins, &rate)
|
|
Packit |
577717 |
mexErrMsgTxt("Error getting instruction rate.");
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
if(nlhs > 0) {
|
|
Packit |
577717 |
plhs[0] = mxCreateDoubleScalar((double)ins);
|
|
Packit |
577717 |
if(nlhs == 2) {
|
|
Packit |
577717 |
plhs[1] = mxCreateDoubleScalar((double)rate);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
else {
|
|
Packit |
577717 |
mexPrintf("Cannot find the command you specified.\n");
|
|
Packit |
577717 |
mexErrMsgTxt("See the included readme file.");
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|