Back to home page

MITgcm

 
 

    


File indexing completed on 2023-05-28 05:10:56 UTC

view on githubraw file Latest commit b4daa243 on 2023-05-28 03:53:22 UTC
b4daa24319 Shre*0001 /*
                0002  * TAPENADE Automatic Differentiation Engine
                0003  * Copyright (C) 1999-2021 Inria
                0004  * See the LICENSE.md file in the project root for more information.
                0005  *
                0006  */
                0007 
                0008 #include <stdio.h>
                0009 #include <stdlib.h>
                0010 #include <string.h>
                0011 #include <signal.h>
                0012 #include <sys/types.h>
                0013 #include <unistd.h>
                0014 #include <time.h>
                0015 #include <unistd.h>
                0016 
                0017 // Access to the cycle counter
                0018 #define rdtscll(val) \
                0019      __asm__ __volatile__ ("rdtsc" : "=A" (val))
                0020 
                0021 #define ENABLE_LINE_RECORDING 1
                0022 
                0023 unsigned long long int mytime_() {
                0024         unsigned long long int time;
                0025 
                0026         rdtscll(time);
                0027         return time ;
                0028 }
                0029 
                0030 // Access to stacks size
                0031 extern long int bigStackSize;
                0032 extern long int smallstacksize_();
                0033 
                0034 
                0035 // Declaration of the event list data structures
                0036 #define ARRAY_SIZE 100000
                0037 struct event {
                0038                 int kind;
                0039                 char *function;
                0040                 int len;
                0041                 unsigned long long int time;
                0042                 int stacksize;
                0043 #ifdef ENABLE_LINE_RECORDING
                0044                 int line;
                0045 #endif
                0046 };
                0047 
                0048 struct list_node {
                0049         struct event array[ARRAY_SIZE];
                0050         struct list_node *next;
                0051 };
                0052 static struct list_node hdcell =  { .next = 0 };
                0053 static struct list_node *tlcell = &hdcell;
                0054 static int cell_index = 0;
                0055 
                0056 // Function to traverse the list of events
                0057 static void traverse_event_list(void (*process)(struct event *ev, void *data), void *data) {
                0058         struct list_node *c = &hdcell;
                0059         
                0060         while (c) {
                0061                 int max = c->next ? ARRAY_SIZE : cell_index;
                0062                 int i;
                0063                 for (i = 0; i < max; ++i)
                0064                         process(&c->array[i], data);
                0065                 c = c->next;
                0066         }
                0067 }
                0068 
                0069 
                0070 // Declaration of profiling functions
                0071 #if 1
                0072 #define profiledebug 
                0073 #else
                0074 #define profiledebug(type) \
                0075         printf("%50s %02u %022llu %010lu %li\n", buffer, type, mytime_(), bigStackSize, smallstacksize_());
                0076 #endif
                0077 enum { BEGIN = 1, END, ENDFWD, BEGINSNAPSHOT, ENDSNAPSHOT, ENDORIG };
                0078 
                0079 int init = 0;
                0080 unsigned long long int beginning_of_time = 0;
                0081 inline static void profile_real(char *function, int flen, int kind) {
                0082     static struct list_node *new = 0;
                0083         if (cell_index >= ARRAY_SIZE) {
                0084                 new = (struct list_node*)calloc(1, sizeof(struct list_node));
                0085                 tlcell->next = new;
                0086                 tlcell = new;
                0087                 new->next = 0;
                0088                 cell_index = 0;
                0089         }
                0090         static unsigned long long int time;
                0091     time = mytime_();
                0092         if (init == 0)
                0093           beginning_of_time = time, init = 1;
                0094         tlcell->array[cell_index].kind = kind;
                0095         tlcell->array[cell_index].function = function;
                0096         tlcell->array[cell_index].len = flen;
                0097         tlcell->array[cell_index].time = time - beginning_of_time;
                0098         tlcell->array[cell_index].stacksize = bigStackSize + smallstacksize_();
                0099         #if 0
                0100         printf("%016llu %09lu %02hhu ", time-beginning_of_time, bigStackSize + smallstacksize_(), kind);
                0101         fwrite(function, 1, flen, stdout);
                0102         printf("\n");
                0103         #endif
                0104         cell_index++;
                0105 }
                0106 
                0107 #define declare_profile(suffix,type) \
                0108 void profile##suffix##_(char *function, int flen) {\
                0109   profile_real(function, flen, type);\
                0110 }
                0111 
                0112 declare_profile(begin,BEGIN)
                0113 declare_profile(end,END)
                0114 declare_profile(endfwd,ENDFWD)
                0115 declare_profile(beginsnapshot,BEGINSNAPSHOT)
                0116 declare_profile(endsnapshot,ENDSNAPSHOT)
                0117 declare_profile(endorig,ENDORIG)
                0118 
                0119 #ifdef ENABLE_LINE_RECORDING
                0120 static int current_line_number = 0;
                0121 
                0122 void profileline_(int *line) {
                0123     current_line_number = *line;
                0124 }
                0125 #endif
                0126 
                0127 // Hashtable data structure
                0128 #define hashtbl_size 4093
                0129 struct hash_cell {
                0130   char *function;
                0131   int len;
                0132 } hashtbl[hashtbl_size];
                0133 // Count of the used element in the hashtable
                0134 int hashtbl_count;
                0135 
                0136 // Simple hash function
                0137 static inline unsigned int hash(unsigned int u) {
                0138   return ((u % hashtbl_size) * 1024 ) % hashtbl_size;
                0139 }
                0140 
                0141 // Simple hash function on strings
                0142 static inline unsigned int hash_string(char *string, int flen) {
                0143   unsigned int ret = 0x55555555;
                0144   while (flen--)
                0145     ret *= ((unsigned char)*string++ * hashtbl_size);
                0146   return hash(ret);
                0147 }
                0148 
                0149 // Min macro
                0150 #define min(a,b) (a < b ? a : b)
                0151 
                0152 // Get the id of a string address, allocate a bucket if new
                0153 static int get(char *function, int flen) {
                0154   int h = hash_string(function, flen);
                0155   while (hashtbl[h].function) {
                0156          if (strncmp(hashtbl[h].function, function, min(flen, hashtbl[h].len)) == 0)
                0157             break;
                0158          h = hash(h);
                0159   }
                0160   hashtbl[h].function = function;
                0161   hashtbl[h].len = flen;
                0162   return h;
                0163 } 
                0164 
                0165 // Functions to serialize integers and known length strings
                0166 static inline void fwrite_int(FILE *f, int i) {
                0167   fwrite(&i, sizeof(int), 1, f);
                0168 }
                0169 static inline void fwrite_llint(FILE *f, unsigned long long int i) {
                0170   fwrite(&i, sizeof(unsigned long long int), 1, f);
                0171 }
                0172 static inline void fwrite_string(FILE *f, char *str, int len) {
                0173   fwrite_int(f, len);
                0174   fwrite(str, (unsigned int) len, 1, f);
                0175 }
                0176 
                0177 // Function to build the hashtable of function names
                0178 static void add_event_to_hashtable(struct event *ev, void *data);
                0179 static void build_hashtable() {
                0180         
                0181         // Initialize the hashtable
                0182         memset(hashtbl, 0, sizeof(struct hash_cell)*hashtbl_size);
                0183         /** Fill the hashtbl */
                0184         traverse_event_list(add_event_to_hashtable, 0);
                0185         /** Compute the size of the hashtbl */
                0186         hashtbl_count = 0;
                0187         int i;
                0188         for (i=0; i < hashtbl_size; ++i)
                0189           if (hashtbl[i].function)
                0190             hashtbl_count++;
                0191 }
                0192 static void add_event_to_hashtable(struct event *ev, void *data) {
                0193   int h = get(ev->function, ev->len);
                0194 }
                0195 
                0196 
                0197 // Serialize event list into a file named tapenade.prof
                0198 struct print_args {
                0199         FILE *prof;
                0200         struct event **stack;
                0201         int *stack_counter;
                0202 };
                0203 static void print_an_event(struct event *ev, void *data);
                0204 void printprofile_() {
                0205         int i = 0;
                0206         FILE *prof = fopen("tapenade.prof", "w");
                0207         if (!prof) {
                0208                 perror("Can't open tapenade.prof");
                0209                 exit(1);
                0210         }
                0211         // Compress the output;
                0212         // Generate a hashtable of the functions name
                0213         // use it to make a map from function name 
                0214         // to numeric id
                0215         build_hashtable();
                0216 
                0217         // Position at the beginning
                0218         fseek(prof, 0, SEEK_SET);
                0219         
                0220         // Dump the hash table
                0221         fwrite_int(prof, hashtbl_count);
                0222         for (i=0; i < hashtbl_size; ++i)
                0223           if (hashtbl[i].function) {
                0224             fwrite_int(prof, i);
                0225             char *string = hashtbl[i].function;
                0226             int string_length = hashtbl[i].len;
                0227             fwrite_string(prof, string, string_length);
                0228           }
                0229           
                0230         // Dump the events
                0231         struct list_node *c = &hdcell;
                0232         struct event *stack[1000];
                0233         int stack_counter = -1;
                0234         struct print_args args = { 
                0235                 .prof = prof, 
                0236                 .stack = stack, 
                0237                 .stack_counter = &stack_counter 
                0238         };
                0239         traverse_event_list(print_an_event, &args);
                0240         
                0241         // For program that aborts too abruptly ( with STOP )
                0242         // Use the return stack image to recreate EXIT events
                0243         for (i=stack_counter; i>-1;i--) {
                0244           struct event *cur = stack[i];
                0245           int h = get(cur->function, cur->len);
                0246           fwrite_int(prof, h);
                0247           fwrite_int(prof, 2); // Explicit ending
                0248           fwrite_llint(prof, cur->time);
                0249           fwrite_int(prof, cur->stacksize);
                0250         }
                0251         fclose(prof);
                0252 }
                0253 void halt_();
                0254 // Utility function for printprofile
                0255 static void print_an_event(struct event *ev, void *data) {
                0256         struct print_args *args = (struct print_args*)data;
                0257         static unsigned long long int last_time = 0;
                0258         
                0259         int h = get(ev->function, ev->len);
                0260         // Keep trace of the return stack depth and values
                0261         switch (ev->kind) {
                0262           case 1:
                0263             *(args->stack_counter) += 1;
                0264             args->stack[*(args->stack_counter)] = ev;
                0265             break;
                0266           case 2:
                0267             *(args->stack_counter) -= 1;
                0268             break;
                0269         }
                0270 //DEBUG        printf("Time: %llu\n", ev->time - begin_time);
                0271         if (last_time && ev->time <= last_time) {
                0272                 printf("Erreur time <= last_time: %llu <= %llu\n", time, last_time);
                0273                 halt_();
                0274         }
                0275         fwrite_int(args->prof, h);
                0276         fwrite_int(args->prof, ev->kind);
                0277         fwrite_llint(args->prof, ev->time);
                0278         fwrite_int(args->prof, ev->stacksize);
                0279         last_time = ev->time;
                0280 }
                0281 
                0282 #include <signal.h>
                0283 void halt_() {
                0284         kill(getpid(), SIGTRAP);
                0285 }