Blame src/Matlab/PAPI_Matlab.c

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
}