Programming Assignment Multi-Threading and Debugging 2 Due Date: Friday night, May 29 @ 11:59pm Overview: The purpose of this mini-assignment is to continue your introduction to parallel programming and multithreading, covering aspects of implementation, benefits and the tradeoffs involved. You will again be provided with skeleton code, and this time you will fill in the functionality where necessary to determine whether a large number is prime or not, both in parallel over many threads simultaneously, and sequentially in one. The program will also record and display the execution time of the calculations using both methods, allowing you to see the relative performance of each. NOTE: Once again, due to the number of classes that use ieng9 and the CPU-intensive nature of this assignment, we are developing and running the multi-threaded programming assignment on the workstations or ieng6! See the section on Getting the Code for more details on how to set up the repository on the workstation. You also get to practice your debugging skills again. We've written a program that will read in a string from the command line and count the characters in the string. We think it's close to working, but we didn't have time to debug it. It's your job to help us track down the bugs and fix it up so we can get to work. You should reference your notes on static vs. global to help you finish this assignment. The debugging exercise will be completed on ieng9. In summary: 1) pamt2 will be developed and executed and turned in with your cs30x account on the workstations in the lab (preferred) or ieng6.ucsd.edu remotely. 2) debug2 will be debugged and executed and turned in with your cs30x account on ieng9.ucsd.edu. Grading: PAMT 2 README: 10 points See "PAMT 2 README File" section Compiling: 10 points Using our Makefile; no warnings, more details below. Correctness: 40 points Includes both abnormal and normal output, both to the correct destination (stderr vs stdout). Debug 2 README: 30 points See "Debug README File" section Correctness: 10 points NOTE: If what you turn in does not compile with given Makefile, you will receive 0 points for this assignment. PAMT 2 Overview Once again, all functions for pamt2 are written in C++. We provide a git repository from which you will clone the starter code. Your job is to fill in the missing functionality. Note that all development and running of pamt2 must take place on the workstations in the labs or on ieng6. Do not develop/run this programming assignment on ieng9. The pamt2.h header file, which is included in the git repository you will clone, contains the following: - the function prototypes - const int numOfThreads, a constant to determine the number of threads the program will spawn C++ routines int main( int argc, char* argv[] ); bool isPrime( long long n, long long lo, long long hi ); Getting the Code for PAMT 2 Like pamt1, there is a git repository already set up containing starter code -- you just have to clone the repository into your class account on a workstation in the basement or on ieng6. Follow the following steps to clone the repository: 1. Log in to a workstation in the basement and open a terminal 2. Clone the repository with the following command: $ git clone ieng9.ucsd.edu:../public/git/pamt2.git You should now have a directory named pamt2. This will contain the starter code for the project, including main.cpp, isPrime.cpp and pamt2.h. You are responsible for filling in some code in main.cpp,as well as the bulk of isPrime.cpp. PAMT 2 Example Output This program takes a list of long long integers (64 bit numbers, up to about 9 quintillion in decimal) and displays information on whether each number is prime and how long it took to determine that. Below are a few examples (bold indicates user input): [cs30xyz]:pamt2$ ./isPrime 8081 246813607 Number of threads = 8 Sequential isPrime for 8081 8081 is prime Completed in 2e-06 sec Async-get parallel isPrime for 8081 8081 is prime Completed in 0.000898 sec Speed-up: 0.00222717 -------------- Sequential isPrime for 246813607 246813607 is prime Completed in 5e-05 sec Async-get parallel isPrime for 246813607 246813607 is prime Completed in 0.00018 sec Speed-up: 0.277778 -------------[cs30xyz]:pamt2$ ./isPrime 790738119649411319 Number of threads = 8 Sequential isPrime for 790738119649411319 790738119649411319 is prime Completed in 3.52902 sec Async-get parallel isPrime for 790738119649411319 790738119649411319 is prime Completed in 0.892324 sec Speed-up: 3.95487 -------------[cs30xyz]:pamt2$ ./isPrime 6312646216567629137 Number of threads = 8 Sequential isPrime for 6312646216567629137 6312646216567629137 is prime Completed in 11.037 sec Async-get parallel isPrime for 6312646216567629137 6312646216567629137 is prime Completed in 2.68558 sec Speed-up: 4.10972 -------------[cs30xyz]:pamt2$ ./isPrime 9223372036854775783 Number of threads = 8 Sequential isPrime for 9223372036854775783 9223372036854775783 is prime Completed in 11.5436 sec Async-get parallel isPrime for 9223372036854775783 9223372036854775783 is prime Completed in 2.7456 sec Speed-up: 4.2044 -------------- Note that the first group of results for each number is for sequential mode (checking each possible factor of the number in sequence in a single thread), while the second group of results is for parallel mode (dividing up the possible factors into ranges, launching a number of threads that each check a range of factors, and then checking the return value from each thread). Like last time, the speedup is the factor by which parallel computation of the result is faster than sequential. A speedup of 1 would mean that both methods are about equally fast, while a speedup of less than 1 would indicate that the sequential mode is better (the overhead of forking and joining threads can dominate small problems), and a speedup of greater than 1 would indicate that the parallel mode is better. Your output might not be exactly the same as the sample output, but it should look reasonable and justifiable. Here are some large numbers for you to test your program’s correctness and speed-up: 489133282872437277 // not prime; sequential performs better 87178291199 70368760954879 688846502588399 32361122672259149 489133282872437279 790738119649411319 6312646216567629137 9223372036854775783 PAMT 2 Modules 1. main.cpp int main( int argc, char* argv[] ); The driver of the program. For each number entered on the command line, main() calls gettimeofday() to get the start time, and then calls isPrime() to run the calculations sequentially. Upon return, gettimeofday() is called again to get the end time. The time difference is then calculated and the results of the sequential run are printed to stdout. Everything up to this point is given to you in the starter code. Next, we will partition the factor range into N separate pieces, where N = # of threads supported by the machine (you can use the numOfThreads constant defined in pamt2.h) and create N - 1 new threads (the Nth thread is just main). An array of bools is then created to store the results of the calculations for each partition and a thread is launched to work on each part of the factor range, each calling isPrime() with low (inclusive) and high (exclusive) factor arguments that define the boundaries that each thread is operating on, and each returning its result into the array of bools. You will have to calculate the partition size and fill in the call to isPrime() with the appropriate arguments. Now the results need to be combined. The program should iterate through the array of bools, checking the values returned by each thread's call to isPrime(). If any returned false, set a variable to indicate that the number is not prime and then break out of the loop. If all parallel calls to isPrime() returned true, then the number is prime and you should set the relevant variable accordingly. It is your responsibility to implement the functionality described in this paragraph. gettimeofday() is called before the parallel computations begin and again after they are completed. The time difference and the speedup are then calculated, and the results of the parallel run are printed to stdout. Note: There are several comments marked TODO in main.cpp that show you where you should make additions/changes. You do not need to (and in fact should not) make changes to main.cpp anywhere except at these points. 2. isPrime.cpp bool isPrime( long long n, long long lo, long long hi ); isPrime() takes the number n which we are checking to the primality of, lo which is the low (inclusive) range of possible factors to check, and hi which is the high (exclusive) range of possible factors to check. The general algorithm is that it will iterate through each factor from lo to hi (inclusive of lo, but exclusive of hi), iterating by two each time, and returning false if any factors evenly divide into n. If you make it through the range of factors without returning false, then return true. For the full details regarding the algorithm you must implement, refer to the comments in the provided isPrime.cpp file. It is your responsibility to implement all of the functionality as described there. PAMT 2 README File Along with your source code, you will be turning in a README (use all caps and no file extension for example, the file is README and not README.txt) file with every assignment. Use vi/vim to edit this file! Your README file for this and all assignments should contain: - Header with your name, cs30x login - High level description of what your program does - How to compile it (usually just typing "make") - How to run it (give an example) - An example of normal output and where that normal output goes (stdout or a file or ???) - An example of abnormal/error output and where that error output goes (stderr usually) - How you tested your program - Anything else that you would want/need to communicate with someone who has not read the writeup - Answers to questions (if there are any) Questions to Answer for the README 1. Try running isPrime on the very large prime number 426110284379068259. You should see that the sequential version takes much longer than the parallel version. What results do you see when you run isPrime on the nearby composite number 426110284379068249? 2. How do you explain the results from the previous question? (It may be useful to know that 426110284379068249 = 653,947,933 * 651,596,653 and that the square root of 426110284379068249 = 652,771,234). 3. Now try running isPrime on another nearby composite 426110284379068257. What results do you see this time? 4. How do you explain those results? (It may be useful to know that 426110284379068257 = 3 * 47 * 3022058754461477). Debugging Exercise 2 Overview The purpose of this program is to read in a single string from the command line and count the characters in this string. The main() function is written in C, and it will find the counts with help from a C helper function. We provide all of the code to you, but the code doesn't quite compile or work as it should. It is up to you to track down the bugs and fix them. There are a total of 5 bugs in the source code. You are required to record ALL of the bugs we placed and the solution for each bug. See the section on Debug README File for more details. C routines int main( int argc, char* argv[] ); int* count( char* str ); Getting the Code for Debugging Exercise For debug2 (the debugging exercise), you will develop on ieng9 as you do for most programming assignments. However, we will provide you with the buggy code. Simply go to your home directory and copy the whole folder to your home directory: $ cd ~ $ cp -r ~/../public/debug2 . This will provide you with all of the buggy source code. All you have to do is fix the code and detail in a README file exactly what fixes you had to make to get this code to work properly - line numbers, what the line looked before and after your fix, etc. Be sure to include a short explanation of how you debugged each problem. Debugging Exercise 2 Example Output The program takes one string argument from the command line: $ ./countChars STRING Below are a few examples (bold indicates user input): [cs30xyz@ieng9]:debug2$ ./countChars Usage: ./countChars STRING If the user didn't pass in the expected number of arguments, the program will print usage. [cs30xyz@ieng9]:debug2$ ./countChars doge Counting number of characters for "doge"... Character Character Character Character d e g o appeared appeared appeared appeared 1 1 1 1 times times times times "doge" has a total of 4 character(s) wow 4 different ascii character(s) much unique so skill As you can see, the program prints out the characters and the number of times they appear in the input string. The program also prints out the total number of characters and the total number of unique characters in the string. [cs30xyz@ieng9]:debug2$ ./countChars supercalifragilisticexpialidocious Counting number of characters for "supercalifragilisticexpialidocious"... Character a appeared 3 times Character c appeared 3 times Character d appeared 1 times Character Character Character Character Character Character Character Character Character Character Character Character e f g i l o p r s t u x appeared appeared appeared appeared appeared appeared appeared appeared appeared appeared appeared appeared 2 1 1 7 3 2 2 2 3 1 2 1 times times times times times times times times times times times times "supercalifragilisticexpialidocious" has a total of 34 character(s) wow 15 different ascii character(s) much unique so skill The program simply counts the number of times each ascii characters appear in the string. The program is expected to work on long words and phrases that have length less than 80 characters. [cs30xyz@ieng9]:debug2$ ./countChars "J.A.R.V.I.S. is just a rather very intelligent system." Counting number of characters for "J.A.R.V.I.S. is just a rather very intelligent system."... Character Character Character Character Character Character Character Character Character Character Character Character Character Character Character Character Character Character Character Character Character Character Character . A I J R S V a e g h i j l m n r s t u v y appeared appeared appeared appeared appeared appeared appeared appeared appeared appeared appeared appeared appeared appeared appeared appeared appeared appeared appeared appeared appeared appeared appeared 7 7 1 1 1 1 1 1 2 5 1 1 3 1 2 1 2 3 4 5 1 1 2 times times times times times times times times times times times times times times times times times times times times times times times "J.A.R.V.I.S. is just a rather very intelligent system." has a total of 54 character(s) wow 23 different ascii character(s) much unique so skill Debugging C Modules 1. main.c int main( int argc, char *argv[] ); The main driver of this program. It first checks the user has entered the right number of arguments. Then it copies the string argument into a local string and calls count(). It loops through the counts array and prints out the characters and their counts if their counts are greater than 0. Finally it prints the total number of characters and the total number of unique characters in the string. 2. count.c int* count( char* str ); This helper method counts the appearances of ascii characters in a given string. It creates an int array of size 256 and increments the element if the ascii character has the same ascii value as the index of the element. It also counts the number of characters in the string by calling a C routine strlen(). Debugging 2 README File For the debugging assignment only, you do not have to include the usual high level description, how tested, etc. You will, however, have to list each of the compilation errors you encountered and the fix you made to correct the error (include the compilation error, the file name, the line number, and the new code). You will also have to solve several logic errors. Again, for each problem, describe the error and describe your solution for fixing it, including the file name, line number, and code for your fix. As a guideline, there should be 3 compilation errors and 2 functionality problems. Make sure you locate all of them!! (Note: When we say there are 3 compilation errors, we mean that there are three fixes you'll have to make, not that there are three errors that are printed to the screen). Reference your lecture notes on static vs. global to help you with this assignment. Turnin Instructions Complete Turnin - due Friday night, May 29 @ 11:59 pm Once you have checked your output, compiled, executed your code, and finished your README file (see below), you are ready to turn it in. Before you turn in your assignment, you should do make clean in order to remove all the object files, lint files, core dumps, and executables. How to Turn in an Assignment First, you need to have all the relevant files in a subdirectory of your home directory. PAMT 2 cse30turnin pamt2 In your cs30x account on the lab workstations of ieng6. You will not be able to turn in pamt2 on ieng9. DEBUG 2 cse30turnin debug2 In your cs30x acoount on ieng9. You will not be able to turn-in debug2 on ieng6. Style Requirements You will be graded for the style of programming on all the assignments. A few suggestions/requirements for style are given below. Read carefully, and if any of them need clarification do not hesitate to ask. - Use reasonable comments to make your code clear and readable. - Use file headers and function header blocks to describe the purpose of your programs and functions. Sample file/function headers are provided with PA0. - Explicitly comment all the various registers that you use in your assembly code. - In the assembly routines, you will have to give high level comments for the synthetic instructions, specifying what the instruction does. - You should test your program to take care of invalid inputs like nonintegers, strings, no inputs, etc. This is very important. Points will be taken off if your code doesn't handle exceptional cases of inputs. - Use reasonable variable names. - Error output goes to stderr. Normal output goes to stdout. - Use #defines and assembly constants to make your code as general as possible. - Use a local header file to hold common #defines, function prototypes, type definitions, etc., but not variable definitions. - Judicious use of blank spaces around logical chunks of code makes your code much easier to read and debug. - Keep all lines less than 80 characters, split long lines if necessary. - Use 2-4 spaces for each level of indenting in your C source code (do not use tab). Be consistent. Make sure all levels of indenting line up with the other lines at that level of indenting. - Do use tabs in your Assembly source code. - Always recompile and execute your program right before turning it in just in case you commented out some code by mistake. - Before running turnin please do a make clean in your project directory. - Do #include only the header files that you need and nothing more. - Always macro guard your header files (#ifndef O #endif). - Never have hardcoded magic numbers. This means we shouldn't see magic constants sitting in your code. Use a #define if you must instead.
© Copyright 2024