[In C] Part 1: Your program will receive the name of an ASCII text file as a com
ID: 3592398 • Letter: #
Question
[In C]
Part 1:
Your program will receive the name of an ASCII text file as a command-line argument and output the number of each kind of ASCII character in the file.
In your code, set up a 64KB (65,536 bytes) buffer in global memory and read the contents of the file into the buffer (or as much of it as will fit).
Then partition the buffer and spawn a number of threads to count the number of occurrences of each ASCII character in each partition. (Use #define directive to set the number of threads to 8.)
Have each thread record these counts in a separate 128- element int array in global memory (stored collectively as a 2-dimensional int array).
The partition bounds can be calculated in the main thread to be roughly equal in size and then passed to each worker thread using a struct.
You will also need to pass a thread index to each thread so that it knows where to write its local count in the global 2-dimensional int array.
Once the worker threads finish writing their local counts, they should exit.
After spawning the worker threads, the main thread should wait for them all to complete.
It should then add the partition counts for each ASCII character and print each overall count. (For nonprintable and white space ASCII characters, i.e., ASCII characters with decimal values smaller than 33, you should just print the hexadecimal character code.)
Here is the example execution result with the test file:
0 occurrences of 0x0
0 occurrences of 0x1
0 occurrences of ‘!’
500 occurrences of ‘A’
500 occurrences of ‘B’
500 occurrences of ‘C’
500 occurrences of ‘D’
...
Hints:
You can use the function fopen()to open a file, and then use fread() to read the contents of the file into a buffer.
You should use the functions pthread_attr_init(), pthread_create(), pthread_exit() and pthread_join()to create and manage the threads.
Part 2:
You will then change the program and compare the results with and without synchronization. Use a one-dimensional global int array this time, to hold all of the character counts. All the threads increment the same array entries without using any synchronization. Then, create a second version of the program that protects the increment of the global int array using a mutex. Run both versions on the same file and compare the character counts.
In order to observe the differences in the results of the two programs, we need to use a Ubuntu virtual machine with multiple CPUs. Below are the steps to change the number of CPUs in virtualbox:
1. Shut down the Ubuntu virtual machine;
2. Go to “Setting” -> “Systems” -> “Processors”.
3. Change the number of CPUs.
Hints:
Use the functions pthread_mutex_init(), pthread_mutex_lock()and pthread_mutex_unlock()to create, acquire, and release the mutex, respectively. Name your C program without synchronization as “ASCIICount2”, and name your C program with synchronization as “ASCIICountS”.
Compare the character counts of both programs on the same text file.
Explanation / Answer
#include <stdio.h>
#include <pthread.h>
#include <time.h>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
//define the thread count as 8
#define NUMBER_OF_THREAD 8
//set the buffer of length 65536 bytes
#define BUFFERLENGTH 65536
//global 128 element 2d int array
int countCharacters[NUMBER_OF_THREAD][128];
//character array
char buffer[BUFFERLENGTH];
//structure to store the thread information
typedef struct{
int thred_limit;
int count_thread;
} myThread;
//the function to perform the thread run
void *threadRun(void *arrayMythread) {
int itr, locationOfThread;
char ascii_char_encoutered;
myThread myThreadInstance = *(myThread*) arrayMythread;
locationOfThread = myThreadInstance.count_thread * myThreadInstance.thred_limit;
ascii_char_encoutered = buffer[locationOfThread];
//the for loop to process each thread
for(itr = 0; locationOfThread < BUFFERLENGTH && itr < myThreadInstance.thred_limit; itr++) {
ascii_char_encoutered = buffer[locationOfThread++];
countCharacters[myThreadInstance.count_thread][ascii_char_encoutered]++;
}
pthread_exit(NULL);
}
//function to compute the time
double timeInSec(void){
return (double)clock()/CLOCKS_PER_SEC;
}
//the main function
int main(int argc, char* argv[]){
//the pthread array
pthread_t arrayPthread[NUMBER_OF_THREAD];
//create the structre array
myThread arrayMythread[NUMBER_OF_THREAD];
//local variables
int itr, i, asciiFile, threadParts, totalNumOfchar, threadObj;
double threadVal;
//open the file that passed as first commandLine
asciiFile = open(argv[1], O_RDONLY);
//if error in opening the file
if (asciiFile < 0){
fprintf(stderr, "File Open error! ");
return -1;
}
asciiFile = read(asciiFile, buffer, BUFFERLENGTH);
threadVal = timeInSec();
threadParts = (double) asciiFile / (double) NUMBER_OF_THREAD;
close(asciiFile);
for(itr = 0; itr < NUMBER_OF_THREAD; itr++) {
arrayMythread[itr].count_thread = itr;
arrayMythread[itr].thred_limit = threadParts;
threadObj = pthread_create(&arrayPthread[itr], NULL, &threadRun, &arrayMythread[itr]);
if(threadObj < 0)
printf("Error creating thread! %itr ", itr);
}
itr = 0;
do{
pthread_join(arrayPthread[itr], NULL);
itr++;
} while (itr < NUMBER_OF_THREAD);
for(itr = 0; itr < 128; itr++) {
totalNumOfchar = 0;
for(i = 0; i < NUMBER_OF_THREAD; i++) {
totalNumOfchar += countCharacters[i][itr];
}
printf("%i occurrences of ", totalNumOfchar);
if(itr < 33 || itr == 127){
printf("%#0x ", itr);
}
else{
printf("%c ", itr);
}
}
threadVal = timeInSec() - threadVal;
return 0;
}
Related Questions
drjack9650@gmail.com
Navigate
Integrity-first tutoring: explanations and feedback only — we do not complete graded work. Learn more.