#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/time.h>
#include <unistd.h>
#include <iostream>
#include <pthread.h>
#include <sstream>
#include <fstream>
#include <string.h>
using namespace std;
#define loopc 4294967295
int FUN;
volatile float b = 1.6, c = 5.7, d = 7.2, e = 1.2, f = 1.1;
volatile int b1 = 2, c1 = 3, d1 = 4, e1 = 5, f1 = 2;
timeval start_time, end_time;
timeval *start_time1, *end_time1;
//Set the user defined parameters(no. of threads, FLops/Iops)
void set(char *argv[]){
#define NUM atoi(argv[1])
start_time1 = (timeval *)malloc(sizeof(timeval) * NUM);
end_time1 = (timeval *)malloc(sizeof(timeval) * NUM);
FUN = atoi(argv[2]);
}
static inline u_int64_t
rdtsc() {
u_int64_t d;
// Instruction is volatile because we don't want it to move
// over an adjacent gettimeofday. That would ruin the timing
// calibrations.
__asm__ __volatile__("rdtsc" : "=&A" (d));
return d;
}
// Compute 64 bit value / timeval (treated as a real).
static inline u_int64_t
operator /(u_int64_t v, timeval t) {
return u_int64_t(v / (double (t.tv_sec) + double (t.tv_usec) / 1000000.));
}
// Compute left - right for timeval structures.
static inline timeval
operator -(const timeval &left, const timeval &right) {
u_int64_t left_us = (u_int64_t) left.tv_sec * 1000000 + left.tv_usec;
u_int64_t right_us = (u_int64_t) right.tv_sec * 1000000 + right.tv_usec;
u_int64_t diff_us = left_us - right_us;
timeval r = {diff_us / 1000000, diff_us % 1000000};
return r;
}
//Compute FLOPS of CPU
void *floptask(void *arg){
int tid;
tid = *((int *) arg);
volatile float a;
gettimeofday(&start_time1[tid], 0);
for (volatile u_int32_t rl_index = 0; rl_index < loopc; ++rl_index) {
a = b + c + d + e + f;
}
gettimeofday(&end_time1[tid], 0);
}
//Compute IOPS of CPU
void *ioptask(void *arg){
int tid;
tid = *((int *) arg);
volatile int a1;
gettimeofday(&start_time1[tid], 0);
for (volatile u_int32_t rl_index = 0; rl_index < loopc; ++rl_index) {
a1 = b1 + c1 + d1 + e1 + f1;
}
gettimeofday(&end_time1[tid], 0);
}
int main(int argc, char *argv []) {
if (argc < 3) {
printf("\nPlease enter all the required parameters\n");
exit(0);
} else {
set(argv);
}
set(argv);
int i, thd_args[NUM], rc;
pthread_t threads[NUM];
typedef void *(*func)(void *);
func farr[2] = {NULL};
farr[0] = &floptask;
farr[1] = &ioptask;
// Thread creation
for (i = 0; i < NUM; ++i) {
thd_args[i] = i;
printf("In main: creating thread %d\n", i);
rc = pthread_create(&threads[i], NULL, farr[FUN], (void *) &thd_args[i]);
}
//Thread join
for (i = 0; i < NUM; ++i) {
rc = pthread_join(threads[i], NULL);
}
//Empty loop time
gettimeofday(&start_time, 0);
for (volatile u_int32_t rl_index = 0; rl_index < loopc; ++rl_index) {
}
gettimeofday(&end_time, 0);
u_int64_t emps, empe, empt, tot;
emps = (u_int64_t) start_time.tv_sec * 1000000 + start_time.tv_usec;
empe = (u_int64_t) end_time.tv_sec * 1000000 + end_time.tv_usec;
empt = empe - emps;
tot = NUM * empt;
//Calculate the start time of first thread and end time of last thread
u_int64_t dst[NUM], det[NUM], fst = 0, fet = 0;
for(i = 0; i < NUM; i++){
dst[i] = (u_int64_t) start_time1[i].tv_sec * 1000000 + start_time1[i].tv_usec;
det[i] = (u_int64_t) end_time1[i].tv_sec * 1000000 + end_time1[i].tv_usec;
}
fst = det[NUM - 1];
for(i = 0; i < NUM; i++){
if(det[i] > fet){
fet = det[i];
}
if(fst > dst[i]){
fst = dst[i];
}
}
double ops;
ops = (4 * loopc * NUM)/(fet - fst - empt);
cout<"Operations: "<<<ops<<endl; // Result
//Write the results to file
stringstream name;
string fname;
name << "CPU_" << FUN << "_" << NUM << ".txt";
fname = name.str();
ofstream myfile;
myfile.open(fname.c_str(), ios::app);
if (myfile.is_open()) {
myfile << ops <<endl;
myfile.close();
}
}