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