/* * Name read_random * Description Read all the files in a random order. * - The files to be read must be opened and placed in share_it.fd_list * We choose the files in a random order, so that the effects of * prefetching are minimized. * - Reads the number of files FILE_COUNT with random access by reading a block * of BLOCK_SIZE in each read operation. * - Random access offset is determined by share_it.index. * - Read block sizes are determined by share_it.block_size. * - Defaults are same as read_sequential. * - Measures only read. Overhead is only the overhead of measuring time * itself. * Input struct share_it * Output Boolean to indicate if all reads succeed. */ bool read_random(struct share_it* my_state) { size_t size = my_state->size; timestamp start = 0; timestamp end = 0; int bytes = 0; int i = 0; for (i = 0; i < my_state->count; i++) { size_t size = my_state->size; int fd = my_state->fd_list[i]; int j = 0; while ((size > 0)) { if (lseek(fd, my_state->offsets[j] * BLOCK_SIZE, SEEK_SET) == -1) { int err = errno; printf("Seek to start of file failed with errno %d\n", err); exit(1); } RDTSCP(start); bytes = read(fd, my_state->buf, my_state->block_size); RDTSCP(end); if (bytes <= 0 || bytes != my_state->block_size) return false; dummy_call(my_state->buf); *(my_state->total_bytes) += bytes; my_state->duration += (end - start); size -= bytes; j++; } } return true; }
/* * Name read_sequential * Description Read all the files in a sequential way. * - The files to be read must be opened and placed in share_it.fd_list * We choose the files in a random order, so that the effects of * prefetching are minimized. * - Reads the number of files FILE_COUNT sequentially by reading a block * of BLOCK_SIZE in each read operation. * - Small files are 64 bytes - 32 kB. * - Big files are 32 kb onwards. * - For small files, I have meassured with block size as 64 bytes * For big files, I have measured with block size as 32 kB * - This routine is also used to measure the time to read a full file by * share_it.block_size to same as file size. * - Measures only read. Overhead is only the overhead of measuring time * itself. * Input struct share_it * Output Boolean to indicate if all reads succeed. */ bool read_sequential(struct share_it* my_state) { size_t size = my_state->size; timestamp start = 0; timestamp end = 0; int bytes = 0; int i = 0; for (i = 0; i < my_state->count; i++) { size_t size = my_state->size; int fd = my_state->fd_list[i]; if (lseek(fd, 0, SEEK_SET) == -1) { int err = errno; printf("Seek to start of file failed with errno %d\n", err); exit(1); } while ((size > 0)) { RDTSCP(start); bytes = read(fd, my_state->buf, my_state->block_size); RDTSCP(end); if (bytes <= 0 || bytes != my_state->block_size) { int err = errno; printf("Read failed with err=%d and bytes =%d while block_size=%zu\n", errno, bytes, my_state->block_size); return false; } dummy_call(my_state->buf); *(my_state->total_bytes) += bytes; my_state->duration += (end - start); size -= bytes; } } return true; }
int main(int argc, char** arv) { ull start; ull end; ull diff; RDTSCP(start); void* ptr = malloc(sizeof(void*)); RDTSCP(end); diff = end - start; write(1, &diff, sizeof(ull)); return 0; }
void time_pthread(){ pthread_t thr; uint val; unsigned long diff; unsigned long best = (unsigned long) -1; int x; for(x = 0;x < RUNS;x++){ /* Timing section */ RDTSCP(start); pthread_create(&thr, NULL, pthread_func, NULL); pthread_join(thr, (void **)NULL); diff = end - start; /* End section */ if(diff < best) best = diff; } diff = best; printf("%lu\n", diff); int file = open(OUTPUT_FILE, O_APPEND | O_RDWR | O_CREAT, 0644); if(file < 0) { printf("BAD FILE!\n"); exit(EXIT_FAILURE); } char numbuffer[512]; snprintf(numbuffer, 512, "%lu\n", diff); write(file, numbuffer, strlen(numbuffer)); close(file); }
/* * Name open_read_close * Description This metric is only applicable for small files. * - Measures the time taken to open a small file, read all of the file and * close the file. * - Files to be opened/read/closed are chosen in random ( lessen prefetching * effects.) * - Overhead : one if-loop + overhead of measuring time. * Input struct share_it * Input filepath - to pick files from. * Output Boolean to indicate if all reads succeed. */ bool open_read_close(struct share_it* my_state, char *filepath) { timestamp start = 0; timestamp end = 0; int bytes = 0; struct drand48_data randBuffer; srand48_r(time(NULL), &randBuffer); int i = 0; long int random = 0; int idx = 0; for (i = 0; i < my_state->count; i++) { lrand48_r(&randBuffer, &random); idx = random % MAX_FILES + 1; char num[5]; sprintf(num, "%d", idx); char my_file[100] = {'\0'}; strcat(my_file, filepath); strcat(my_file, "/file"); strcat(my_file, num); RDTSCP(start); int fd = open(my_file, FLAGS); if (fd == -1) { int err = errno; printf("Could not open file descriptor for file %s. Error = %d\n", my_file, err); return false; } bytes = read(fd, my_state->buf, my_state->block_size); close(fd); RDTSCP(end); if (bytes <= 0 || bytes != my_state->block_size) return false; dummy_call(my_state->buf); *(my_state->total_bytes) += bytes; my_state->duration += (end - start); } return true; }
/* * Name write_random * Description Write all the files in a random order. * - The files to be written must be opened and placed in share_it.fd_list * We choose the files in a random order, so that the effects of * prefetching are minimized. * - Writes the number of files FILE_COUNT with random access by reading a block * of BLOCK_SIZE in each write operation. * - Random access offset is determined by share_it.index. * - Write block sizes are determined by share_it.block_size. * - Defaults are same as write_sequential. * - Measures only write. Overhead is only the overhead of measuring time * itself. * Input struct share_it * Output Boolean to indicate if all writes succeed. */ bool write_random(struct share_it* my_state) { size_t size = my_state->size; timestamp start = 0; timestamp end = 0; int bytes = 0; int rand_bytes = 0; int i = 0; for (i = 0; i < my_state->count; i++) { size_t size = my_state->size; int fd = my_state->fd_list[i]; int j = 0; while ((size > 0)) { // fill buf with random data /* rand_bytes = syscall(SYS_getrandom, my_state->buf, my_state->block_size, 0); if (rand_bytes == -1 || rand_bytes != my_state->block_size) { int err = errno; printf("Could not get random data, failed with err=%d and bytes =%d while block_size=%zu\n", errno, bytes, my_state->block_size); return false; } */ if (lseek(fd, my_state->offsets[j] * BLOCK_SIZE, SEEK_SET) == -1) { int err = errno; printf("Seek to start of file failed with errno %d\n", err); exit(1); } RDTSCP(start); bytes = write(fd, my_state->buf, my_state->block_size); RDTSCP(end); if (bytes <= 0 || bytes != my_state->block_size) return false; dummy_call(my_state->buf); *(my_state->total_bytes) += bytes; my_state->duration += (end - start); size -= bytes; j++; } } return true; }
void *pthread_func(void *argument){ RDTSCP(end); //get the cycle counter right away here pthread_exit(NULL); return NULL; }
int main(int argc, char **argv) { if ( argc != 3) { printf("Usage: ./mp_small <mnt_directory> <num_of_threads>\n"); exit(1); } // Get the mount directory char *path = argv[1]; char *filename = "file"; // Set the number of threads. int nthreads = atoi(argv[2]); omp_set_num_threads(nthreads); int tid; double total_time = 0; double read_data = 0; double throughput = 0; struct drand48_data randBuffer; srand48_r(time(NULL), &randBuffer); timestamp start = 0; timestamp end = 0; /* Fork a team of threads with each thread having a private tid variable */ #pragma omp parallel private(tid) { tid = omp_get_thread_num(); // Setup int *fd_list = (int *) malloc( sizeof(int) * FILE_COUNT); // Open all the files int i = 0; long int random = 0; int idx = 0; size_t total_bytes = 0; for ( i = 0; i < FILE_COUNT; i++) { // Prepare the file name lrand48_r(&randBuffer, &random); idx = random % MAX_FILES + 1; char num[5]; sprintf(num, "%d", idx); char my_file[100] = {'\0'}; strcat(my_file, path); strcat(my_file, "/"); strcat(my_file, filename); strcat(my_file, num); fd_list[i] = open(my_file, FLAGS); int err = errno; if (fd_list[i] == -1) { printf(" %d : Could not open file descriptor for file %s. Error = %d\n", tid, my_file, err); exit(1); } } struct stat sb; if (fstat(fd_list[0], &sb) == -1) { printf("%d : File stat failed for file\n", tid); exit(1); } char *buf = (char *)malloc(BLOCK_SIZE); int pages = sb.st_size / BLOCK_SIZE; int *index = (int *)malloc(sizeof(int) * pages); randomize(index, pages); // Prepare for read. struct share_it state; state.fd_list = fd_list; state.offsets = index; state.buf = buf; state.size = sb.st_size; state.block_size = (32 * 1024); state.count = FILE_COUNT; state.duration = 0; state.total_bytes = &total_bytes; // Collect stats #pragma omp barrier if ( tid == 0) { RDTSCP(start); } // Wait to read #pragma omp barrier bool success = read_random(&state); if (!success) { printf("%d : Read failed\n", tid); exit(1); } #pragma omp barrier if ( tid == 0) { RDTSCP(end); } #pragma omp barrier // Close all the files. for( i = 0; i< FILE_COUNT; i++) close(fd_list[i]); free(fd_list); free(buf); if (tid == 0) { read_data = sb.st_size * FILE_COUNT; } } /* All threads join master thread and terminate */ double val = (read_data * nthreads * (CPU_FREQ * 1000000) ) / ( (end - start) * 1024 * 1024 * 1024); // GB/sec printf("%lf\n", val); }