added example files for cpu pinning and clock skew detection
authoradash <adash>
Fri, 11 Sep 2009 22:28:58 +0000 (22:28 +0000)
committeradash <adash>
Fri, 11 Sep 2009 22:28:58 +0000 (22:28 +0000)
Robust/src/Benchmarks/SingleTM/MicroBenchmarks/checkClockSync.c [new file with mode: 0644]
Robust/src/Benchmarks/SingleTM/MicroBenchmarks/checkCpuPinning.c [new file with mode: 0644]
Robust/src/Benchmarks/SingleTM/MicroBenchmarks/cpuPinningforPthreads.c [new file with mode: 0644]
Robust/src/Benchmarks/SingleTM/MicroBenchmarks/cpuPinningforPthreads2.c [new file with mode: 0644]

diff --git a/Robust/src/Benchmarks/SingleTM/MicroBenchmarks/checkClockSync.c b/Robust/src/Benchmarks/SingleTM/MicroBenchmarks/checkClockSync.c
new file mode 100644 (file)
index 0000000..251c5bd
--- /dev/null
@@ -0,0 +1,86 @@
+#include <stdlib.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <pthread.h>
+#include <sys/time.h>
+
+#define THREADS 8
+#define ITERATIONS 100000
+
+pthread_barrier_t barr;
+
+static __inline__ unsigned long long rdtsc(void)
+{
+  unsigned hi, lo;
+  __asm__ __volatile__ ("rdtsc" : "=a"(lo), "=d"(hi));
+  return ( (unsigned long long)lo)|( ((unsigned long long)hi)<<32 );
+}
+
+static __inline__ int64_t timeInMS () //time in microsec
+{
+  struct timeval t;
+
+  gettimeofday(&t, NULL);
+  return (
+      (int64_t)t.tv_sec * 1000000 +
+      (int64_t)t.tv_usec
+      );
+}
+
+void * thd (
+    void * unused
+    ) {
+  int count = 0;
+  unsigned long long tottime, time;
+  while(count<ITERATIONS) {
+    // Wait till we may fire away
+    int rc=pthread_barrier_wait(&barr);
+    if(rc != 0 && rc != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      printf("Could not wait on barrier\n");
+      exit(-1);
+    }
+    //printf("t= %lld\n", rdtsc());
+    //time = timeInMS();
+    time = rdtsc();
+    tottime += time;
+    count++;
+  }
+  printf("time= %lld micro secs\n", tottime/ITERATIONS);
+}
+
+int main (
+    int argc,
+    char ** argv
+    ) {
+  int64_t start;
+  pthread_t t1, t2, t3, t4, t5, t6, t7, t8;
+  int64_t myTime;
+
+  // Barrier initialization
+  if(pthread_barrier_init(&barr, NULL, THREADS))
+  {
+    printf("Could not create a barrier\n");
+    return -1;
+  }
+
+  pthread_create(&t1, NULL, thd, NULL);
+  pthread_create(&t2, NULL, thd, NULL);
+  pthread_create(&t3, NULL, thd, NULL);
+  pthread_create(&t4, NULL, thd, NULL);
+  pthread_create(&t5, NULL, thd, NULL);
+  pthread_create(&t6, NULL, thd, NULL);
+  pthread_create(&t7, NULL, thd, NULL);
+  pthread_create(&t8, NULL, thd, NULL);
+
+  pthread_join(t1, NULL);
+  pthread_join(t2, NULL);
+  pthread_join(t3, NULL);
+  pthread_join(t4, NULL);
+  pthread_join(t5, NULL);
+  pthread_join(t6, NULL);
+  pthread_join(t7, NULL);
+  pthread_join(t8, NULL);
+
+  return 0;
+}
diff --git a/Robust/src/Benchmarks/SingleTM/MicroBenchmarks/checkCpuPinning.c b/Robust/src/Benchmarks/SingleTM/MicroBenchmarks/checkCpuPinning.c
new file mode 100644 (file)
index 0000000..a8ff4b0
--- /dev/null
@@ -0,0 +1,212 @@
+/*******************************************************************
+ * This program has the sole purpose of showing some kernel API 
+ * for CPU affinity for processes. Consider this merely a demo...
+ * 
+ * adash@uci.edu
+ ********************************************************************/
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/sysinfo.h>
+#include <sys/mman.h>
+#include <unistd.h>
+#define  __USE_GNU
+#include <sched.h>
+#include <ctype.h>
+#include <string.h>
+
+/* Create us some pretty boolean types and definitions */
+typedef int bool;   
+#define TRUE  1
+#define FALSE 0 
+
+/* Method Declarations */
+void usage();                              /* Simple generic usage function */
+bool do_cpu_stress(int numthreads);    /* Entry point into CPU thrash   */
+int  do_cpu_expensive_op(int myitem);            /* Single thread cpu intensive   */
+bool check_cpu_expensive_op(int possible_result);/* Compare value to precomputed  */
+
+
+int main(
+    int argc, 
+    char **argv ) 
+{
+  int return_code = FALSE;
+
+  /* Determine the actual number of processors */
+  int NUM_PROCS = sysconf(_SC_NPROCESSORS_CONF);
+  printf("System has %i processor(s).\n", NUM_PROCS);
+
+  /* These need sane defaults, because the values will be used unless overriden */
+  int num_cpus_to_spin = NUM_PROCS; 
+
+  /* Check for user specified parameters */
+  int option = 0; 
+  while ((option = getopt(argc, argv, "m:c:l?ahd")) != -1)
+  {
+    switch (option)
+    {
+      case 'c': /* SPECIFY NUM CPUS TO MAKE BUSY */
+        num_cpus_to_spin = atoi(optarg);
+        if (num_cpus_to_spin < 1)
+        {
+          printf("WARNING: Must utilize at least 1 cpu. Spinning "
+              " all %i cpu(s) instead...\n", NUM_PROCS);
+          num_cpus_to_spin = 1;
+        }
+        else if (num_cpus_to_spin > NUM_PROCS)
+        {
+          printf("WARNING: %i cpu(s), are not "
+              "available on this system, spinning all %i cpu(s) "
+              "instead...\n", num_cpus_to_spin, NUM_PROCS);
+          num_cpus_to_spin = NUM_PROCS;
+        }
+        else
+        { 
+          printf("Maxing computation on %i cpu(s)...\n",
+              num_cpus_to_spin);
+        }
+        break;
+
+
+      case '?':
+        if (isprint (optopt))
+        {
+          fprintf (stderr, 
+              "Unknown option `-%c'.\n", optopt);
+        }
+        else
+        {
+          fprintf (stderr,
+              "Unknown option character `\\x%x'.\n",
+              optopt);
+        }
+        break;
+
+      default:
+        usage(argv[0]);
+        exit(0);
+    }
+  }
+
+  /* Kick off the actual work of spawning threads and computing */
+  do_cpu_stress(num_cpus_to_spin); 
+  return return_code;
+}
+
+
+/* This method simply prints the usage information for this program */
+void usage()
+{
+  printf("[-c  NUM_CPUS_TO_STRESS]\n");
+  printf("If no parameters are specified all cpu's will be made busy.\n");
+  return;
+}
+
+/* This method creates the threads and sets the affinity. */
+bool do_cpu_stress(int numthreads)
+{
+  int ret = TRUE;
+  int created_thread = 0;
+
+  /* We need a thread for each cpu we have... */
+  //pthread_create(&t1, NULL, thd, NULL);
+
+  while ( created_thread < numthreads - 1 )
+  {
+    int mypid = fork();
+
+    if (mypid == 0) /* Child process */
+    {
+      printf("\tCreating Child Thread: #%i\n", created_thread);
+      break;
+    }
+
+    else /* Only parent executes this */
+    { 
+      /* Continue looping until we spawned enough threads! */ ;
+      created_thread++;
+    } 
+  }
+
+
+
+  /* NOTE: All threads execute code from here down! */
+
+  cpu_set_t mask;
+
+  /* CPU_ZERO initializes all the bits in the mask to zero. */ 
+  CPU_ZERO( &mask );  
+
+  printf("created_thread= %d\n", created_thread);
+  /* CPU_SET sets only the bit corresponding to cpu. */
+  CPU_SET( created_thread, &mask );  
+
+  /* sched_setaffinity returns 0 in success */
+  if( sched_setaffinity( 0, sizeof(mask), &mask ) == -1 )
+  {
+    printf("WARNING: Could not set CPU Affinity, continuing...\n");
+  }
+  /* sched_setaffinity sets the CPU affinity mask of the process denoted by pid. 
+     If pid is zero, then the current process is used.
+
+     The affinity mask is represented by the bitmask stored in mask. The least
+     significant bit corresponds to the first logical processor number on the
+     system, while the most significant bit corresponds to the last logical 
+     processor number on the system. A set bit corresponds to a legally schedulable
+     CPU while an unset bit corresponds to an illegally schedulable CPU. In other 
+     words, a process is bound to and will only run on processors whose 
+     corresponding bit is set. Usually, all bits in the mask are set.
+
+     Also the affinity is passed on to any children!
+   */
+
+  /* Now we have a single thread bound to each cpu on the system */
+  int computation_res = do_cpu_expensive_op(41);
+  cpu_set_t mycpuid;  
+  sched_getaffinity(0, sizeof(mycpuid), &mycpuid);
+
+  
+  if ( check_cpu_expensive_op(computation_res) )
+  {
+    printf("SUCCESS: Thread completed computational task, and PASSED integrity check! %x\n",
+        mycpuid);
+    ret = TRUE; 
+  }
+  else 
+  {
+    printf("FAILURE: Thread failed integrity check!\n",
+        mycpuid);
+    ret = FALSE;
+  }  
+
+  return ret;
+} 
+
+
+/* Lame (computationally wasteful) recursive fibonaci sequence finder 
+   Intentionally does not store known computed values. 
+ */
+int do_cpu_expensive_op(int myitem)
+{
+  /* FIXME: Should check myitem size because this could overflow quick */
+  if (myitem == 0 || myitem == 1) 
+  { 
+    return myitem; 
+  }
+
+  return ( do_cpu_expensive_op( myitem - 1 ) + do_cpu_expensive_op( myitem - 2 ) ); 
+}
+
+
+
+/* This method simply takes an integer argument
+   and compares it to a precomputed correct value.
+ */
+bool check_cpu_expensive_op(int possible_result)
+{
+  /* 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987 ... fib(41) = 165580141 */ 
+  int actual_result = 165580141;
+  return ( actual_result == possible_result );
+}
diff --git a/Robust/src/Benchmarks/SingleTM/MicroBenchmarks/cpuPinningforPthreads.c b/Robust/src/Benchmarks/SingleTM/MicroBenchmarks/cpuPinningforPthreads.c
new file mode 100644 (file)
index 0000000..684e20d
--- /dev/null
@@ -0,0 +1,176 @@
+/*******************************************************************
+ * This program has the sole purpose of showing some kernel API 
+ * for CPU affinity used in pthreads. Consider this merely a demo...
+
+ * Uses pthread_setaffinity_np
+ * adash@uci.edu
+ ********************************************************************/
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/sysinfo.h>
+#include <sys/mman.h>
+#include <unistd.h>
+#define  __USE_GNU
+#include <sched.h>
+#include <ctype.h>
+#include <string.h>
+#include <pthread.h>
+
+/* Create us some pretty boolean types and definitions */
+typedef int bool;   
+#define TRUE  1
+#define FALSE 0 
+#define ITERATIONS 1000000
+pthread_barrier_t barr;
+
+
+/* Method Declarations */
+void usage();                              /* Simple generic usage function */
+bool do_cpu_stress(int numthreads);    /* Entry point into CPU thrash */
+static __inline__ unsigned long long rdtsc(void);
+void *thd(void *threadid);
+
+
+int main(
+    int argc, 
+    char **argv ) 
+{
+    int return_code = FALSE;
+
+  /* Determine the actual number of processors */
+  int NUM_PROCS = sysconf(_SC_NPROCESSORS_CONF);
+  printf("System has %i processor(s).\n", NUM_PROCS);
+
+  /* These need sane defaults, because the values will be used unless overriden */
+  int num_cpus_to_spin = NUM_PROCS; 
+
+  // Barrier initialization
+  if(pthread_barrier_init(&barr, NULL, NUM_PROCS))
+  {
+    printf("Could not create a barrier\n");
+    return -1;
+  }
+
+  /* Check for user specified parameters */
+  int option = 0; 
+  while ((option = getopt(argc, argv, "m:c:l?ahd")) != -1)
+  {
+    switch (option)
+    {
+      case 'c': /* SPECIFY NUM CPUS TO MAKE BUSY */
+        num_cpus_to_spin = atoi(optarg);
+        if (num_cpus_to_spin < 1)
+        {
+          printf("WARNING: Must utilize at least 1 cpu. Spinning "
+              " all %i cpu(s) instead...\n", NUM_PROCS);
+          num_cpus_to_spin = 1;
+        }
+        else if (num_cpus_to_spin > NUM_PROCS)
+        {
+          printf("WARNING: %i cpu(s), are not "
+              "available on this system, spinning all %i cpu(s) "
+              "instead...\n", num_cpus_to_spin, NUM_PROCS);
+          num_cpus_to_spin = NUM_PROCS;
+        }
+        else
+        { 
+          printf("Maxing computation on %i cpu(s)...\n",
+              num_cpus_to_spin);
+        }
+        break;
+
+
+      case '?':
+        if (isprint (optopt))
+        {
+          fprintf (stderr, 
+              "Unknown option `-%c'.\n", optopt);
+        }
+        else
+        {
+          fprintf (stderr,
+              "Unknown option character `\\x%x'.\n",
+              optopt);
+        }
+        break;
+
+      default:
+        usage(argv[0]);
+        exit(0);
+    }
+  }
+
+  /* Kick off the actual work of spawning threads and computing */
+  do_cpu_stress(num_cpus_to_spin); 
+  return return_code;
+}
+
+/* This method simply prints the usage information for this program */
+void usage()
+{
+  printf("[-c  NUM_CPUS_TO_STRESS]\n");
+  printf("If no parameters are specified all cpu's will be made busy.\n");
+  return;
+}
+
+/* This method creates the threads and sets the affinity. */
+bool do_cpu_stress(int numthreads)
+{
+  int ret = TRUE;
+  int created_thread = 0;
+
+  pthread_t threads[numthreads];
+  int rc;
+  unsigned long t;
+  for(t=1; t<numthreads+1; t++){
+    rc = pthread_create(&threads[t-1], NULL, thd, (void *)t);
+    if (rc){
+      printf("ERROR; return code from pthread_create() is %d\n", rc);
+      exit(-1);
+    }
+  }
+
+  for(t=1; t<numthreads+1; t++){
+    pthread_join(threads[t-1], NULL);
+  }
+
+  return ret;
+}
+
+void *thd(void *threadid)
+{
+  unsigned long mask;
+  mask = (unsigned long)threadid;
+  printf("Hello World! It's me, thread #%ld!\n", mask);
+
+  /* bind process to processor threadid */
+  if (pthread_setaffinity_np(pthread_self(), sizeof(mask), &mask) <0) {
+    perror("pthread_setaffinity_np");
+  }
+
+  /* calculate the clock skew for each core */
+  int count = 0;
+  unsigned long long tottime, time;
+  while(count<ITERATIONS) {
+    // Wait till we may fire away
+    int rc=pthread_barrier_wait(&barr);
+    if(rc != 0 && rc != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      printf("Could not wait on barrier\n");
+      exit(-1);
+    }
+    time = rdtsc();
+    tottime += time;
+    count++;
+  }
+  printf("time= %lld clock ticks, cpu id= %ld\n", tottime/ITERATIONS, mask);
+}
+
+static __inline__ unsigned long long rdtsc(void)
+{
+  unsigned hi, lo;
+  __asm__ __volatile__ ("rdtsc" : "=a"(lo), "=d"(hi));
+  return ( (unsigned long long)lo)|( ((unsigned long long)hi)<<32 );
+}
diff --git a/Robust/src/Benchmarks/SingleTM/MicroBenchmarks/cpuPinningforPthreads2.c b/Robust/src/Benchmarks/SingleTM/MicroBenchmarks/cpuPinningforPthreads2.c
new file mode 100644 (file)
index 0000000..9ecb2d4
--- /dev/null
@@ -0,0 +1,103 @@
+/*******************************************************************
+ * Example that uses sched_affinity for cpu pinning 
+ *
+ * adash@uci.edu
+ ********************************************************************/
+
+#define _GNU_SOURCE
+
+#include <errno.h>
+#include <pthread.h>
+#include <sched.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/syscall.h>
+#include <unistd.h>
+
+#define ITERATIONS 100000
+pthread_barrier_t barr;
+
+static __inline__ unsigned long long rdtsc(void)
+{
+  unsigned hi, lo;
+  __asm__ __volatile__ ("rdtsc" : "=a"(lo), "=d"(hi));
+  return ( (unsigned long long)lo)|( ((unsigned long long)hi)<<32 );
+}
+
+static void set_affinity(unsigned long cpu)
+{
+  int err;
+  cpu_set_t cpumask;
+
+  CPU_ZERO(&cpumask);
+  CPU_SET(cpu, &cpumask);
+  err = sched_setaffinity(syscall(SYS_gettid),
+      sizeof(cpu_set_t), &cpumask);
+
+  if (err == -1)
+    printf("set_affinity: %s\n", strerror(errno));
+}
+
+static void *_thread(void *data)
+{
+  /* thread_id, cpu id */
+  unsigned long cpu = (unsigned long) data;
+  long retval;
+
+  set_affinity(cpu);
+
+  int count = 0;
+  unsigned long long tottime, time;
+  /* calculate the clock skew for each core */
+  while(count<ITERATIONS) {
+    // Wait till we may fire away
+    int rc=pthread_barrier_wait(&barr);
+    if(rc != 0 && rc != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      printf("Could not wait on barrier\n");
+      exit(-1);
+    }
+    time = rdtsc();
+    tottime += time;
+    count++;
+  }
+  printf("time= %lld clock ticks, cpu id= %ld\n", tottime/ITERATIONS, cpu);
+  pthread_exit(NULL);
+}
+
+int main(int argc, char *argv[])
+{
+  unsigned long nr_cpus;
+  pthread_t *readers;
+  unsigned long i;
+  int signal;
+
+  nr_cpus = sysconf(_SC_NPROCESSORS_ONLN);
+
+  // Barrier initialization
+  if(pthread_barrier_init(&barr, NULL, nr_cpus))
+  {
+    printf("Could not create a barrier\n");
+    return -1;
+  }
+
+  readers = calloc(nr_cpus, sizeof(pthread_t));
+  if (!readers)
+    printf("Out of memory!\n");
+
+  for (i = 0; i < nr_cpus; i++) {
+    int err;
+
+    err = pthread_create(&readers[i], NULL, _thread,
+        (void *) i);
+    if (err)
+      printf("Could not pthread_create(): %s!\n",
+          strerror(errno));
+  }
+
+  for (i = 0; i < nr_cpus; i++)
+    pthread_join(readers[i], NULL);
+
+  return 0;
+}