You are on page 1of 37

BCIT Computing and Information Technology

COMP 8005 Network and Security Applications Development


Due Date: February 1, 2011
Author: Arthur (Wesley) Kenzie A00242330
Assignment 1: Multi-Process versus Multi-Threaded Program Analysis (Final Version)
______________________________________________________________________________

This assignment compares the performance and efficiency of two programs with identical
functionality implemented by way of multiple processes in one program, compared to multiple
threads in the other program.

Introduction ............................................................................................ page 2

Methodology ............................................................................................ page 2

Test A (On Xubuntu Desktop VM) ................................................................. page 4

Test B (Same as Test A, but with 1000x more file I/O) ................................... page 9

Test C (Same as Test A, but with no file I/O) ................................................. page 12

Test D (Same as Test B, but on dedicated server running Ubuntu Server) ......... page 15

Summaries and Conclusions ..................................................................... page 18

Appendix .................................................................................................. page 19

Bibliography ............................................................................................. page 22

Credits ...................................................................................................... page 23

______________________________________________________________________________
Copyright © 2011. Arthur (Wesley) Kenzie. All Rights Reserved. Page 1 of 23
BCIT Computing and Information Technology
COMP 8005 Network and Security Applications Development
Due Date: February 1, 2011
Author: Arthur (Wesley) Kenzie A00242330
Assignment 1: Multi-Process versus Multi-Threaded Program Analysis (Final Version)
______________________________________________________________________________

Introduction

This assignment compares the performance and efficiency of two programs with identical
functionality implemented by way of multiple processes in one program, compared to multiple
threads in the other program. The functionality in each process, and in each thread, consists of a
prime number decomposition algorithm to perform processor-intensive computations, followed by
local file input/output.

Methodology

The multiple process program processes.c is included on the accompanying DVD, along with its
corresponding source code listing at “processes.c program listing.pdf”.

The multiple thread program threads.c is also included on the accompanying DVD, along with its
corresponding source code listing at “threads.c program listing.pdf”.

Each of the programs was written in ANSI C, compiled and linked with gcc version 4.4, and then
run on Ubuntu version 10 Linux. None of the work in this assignment was done on Microsoft
Windows.

The pseudo-code design for both processes.c and threads.c is included in the Appendix.

The prime number decomposition algorithm was borrowed from rosettacode.org. A single integer
is passed to this algorithm, which then calculates the lowest prime numbers which must be
multiplied together to get the product equal to this integer. The GNU multi-precision library
(“gmp”) is used in this algorithm. The more complexity that is required with regards to the prime
numbers to be discovered, the more processor computations are required, and thus the more
elapsed time is required.

The integer passed to each process or thread is determined by command line arguments when the
program is started. Starting either program with 3 different numbers (integers) on the command
line will result in 3 separate processes or threads being created, each with one of the command
line numbers as the integer to be decomposed. Both programs are designed to accept between 3
and 9 numbers, meaning that a minimum of 3 and a maximum of 9 processes or threads will be
created.

The file input/output involves the creation of a unique write-able file, followed by a variable
number of writes (using the fputs() function) into the file, and an equal number of reads (using
fgets() function) from the file. When finished, the file is then closed. The number of writes and
reads defaults to 10, but can be changed by using the --ioloops= command line parameter when
starting up the program. Specifying --ioloops=6 for example, will cause each process or thread to
go through 1,000,000 (10^6) writes and reads.

Four tests were run and tabulated for this assignment, with each test comparing a sampling of
start times and run times for five simultaneous child processes versus five simultaneous threads.
______________________________________________________________________________
Copyright © 2011. Arthur (Wesley) Kenzie. All Rights Reserved. Page 2 of 23
BCIT Computing and Information Technology
COMP 8005 Network and Security Applications Development
Due Date: February 1, 2011
Author: Arthur (Wesley) Kenzie A00242330
Assignment 1: Multi-Process versus Multi-Threaded Program Analysis (Final Version)
______________________________________________________________________________
Three of the tests were done in order to measure the impact of changing some of the functionality
done by each process and by each thread; the fourth test was done in order to measure the
impact of changing the hardware and operating system environment.

The processes were created by way of the C language fork() command. The threads were
implemented using the C language POSIX pthread library. The start times were calculated by
recording the system time just before either the fork() or pthread_create() function calls, and
then passing this system time to the function run by the child process or the thread. The first step
in each process and in each thread was to calculate the elapsed time at that point in time since
the system time passed to it. This elapsed time was what we refer to as the “start time” and it is a
measure of how long it took to get a process or a thread started.

Run times were calculated as the very last step in each process and in each thread. The system
time was recorded at the end of the process or thread, and from that the elapsed time since the
start of the process or thread was calculated, to be the “run time”.

Total times were simply calculated as the sum of the start time and run time of each process or
thread.

A sampling of each test run was done because of the variations encountered in both start times
and run times. Averages, medians, and variances were thus calculated based on the samples.
Each test was run 5 times for the multiple process program (“a1p”) and 5 times for the multiple
thread program (“a1t”), with all known controllable conditions and variables the same for each
sample.

______________________________________________________________________________
Copyright © 2011. Arthur (Wesley) Kenzie. All Rights Reserved. Page 3 of 23
BCIT Computing and Information Technology
COMP 8005 Network and Security Applications Development
Due Date: February 1, 2011
Author: Arthur (Wesley) Kenzie A00242330
Assignment 1: Multi-Process versus Multi-Threaded Program Analysis (Final Version)
______________________________________________________________________________

Test A (On Xubuntu Desktop VM)

This first test was run on an Xubuntu 10.04 32-bit Desktop VM in VMware Workstation on a
Microsoft Windows 7 Ultimate desktop. The VM was configured to use 640MB of RAM, 20GB of
hard disk, and 4 processors, as shown below:

______________________________________________________________________________
Copyright © 2011. Arthur (Wesley) Kenzie. All Rights Reserved. Page 4 of 23
BCIT Computing and Information Technology
COMP 8005 Network and Security Applications Development
Due Date: February 1, 2011
Author: Arthur (Wesley) Kenzie A00242330
Assignment 1: Multi-Process versus Multi-Threaded Program Analysis (Final Version)
______________________________________________________________________________

An example test run was done on January 28, 2011 at 19:17:27 PST, as shown below. The
command line used to start the multiple threads program was:

./a1t 998 992923727 2050700031 883993838 100939437 --ioloops=1

The 5 numbers on the command line correspond to the 5 threads started. The –ioloops=1
argument corresponds to 10 file I/O loops being performed in each thread.

It is readily apparent that thread scheduling performed by the Ubuntu Linux 2.6.32-28 kernel is
not predictable – at least in this VM environment. The program logic in threads.c (see line 156)
shows that each of the threads would have been started in order from 1 to 5. However, execution
of thread 3 is the first to reach the printf() statement (at line 186) which shows its start time of
0.0005 seconds with the number 2050700031. Thread 3 is followed by threads 1, 2, 5 and then 4
to get to this point in the program/thread.

______________________________________________________________________________
Copyright © 2011. Arthur (Wesley) Kenzie. All Rights Reserved. Page 5 of 23
BCIT Computing and Information Technology
COMP 8005 Network and Security Applications Development
Due Date: February 1, 2011
Author: Arthur (Wesley) Kenzie A00242330
Assignment 1: Multi-Process versus Multi-Threaded Program Analysis (Final Version)
______________________________________________________________________________

Here is a summary of the 5 samples taken for the multiple threaded Test A. Start times for each
thread varied from 0.0004 to 0.0021 seconds, with an average of 0.0009 seconds. Total start
times for all threads varied from 0.0039 to 0.0057 seconds, with an average of 0.0046 seconds.

Thread with 10 file I/O  Thread  Thread  Thread  Thread  Thread  Thread 


Totals 
loops  1  2  3  4  5  averages 

run 1 start times  0.0021  0.0011  0.0005  0.0009 0.0011  0.0011  0.0057


run 2 start times  0.0010  0.0008  0.0006  0.0004 0.0011  0.0008  0.0039
run 3 start times  0.0009  0.0009  0.0006  0.0004 0.0015  0.0009  0.0043
run 4 start times  0.0010  0.0009  0.0007  0.0006 0.0021  0.0011  0.0053
run 5 start times  0.0009  0.0007  0.0006  0.0013 0.0005  0.0008  0.0040
Thread average start 
times  0.0012  0.0009  0.0006  0.0007 0.0013  0.0009  0.0046
run 1 run times  3.0784  3.4788  3.0804  3.0858 3.0845  3.1616  15.8079
run 2 run times  0.0030  3.4893  3.1106  0.0045 3.1092  1.9433  9.7166
run 3 run times  0.0032  3.4758  3.0950  3.4775 3.0997  2.6302  13.1512
run 4 run times  0.0040  3.5864  3.2055  0.0093 0.0080  1.3626  6.8132
run 5 run times  0.3874  0.3855  3.5024  0.3860 3.5050  1.6333  8.1663
Thread average run 
times  0.6952  2.8832  3.1988  1.3926 2.5613  2.1462  10.7310
Thread average total 
times  0.6964  2.8840  3.1994  1.3933 2.5625  2.1471  10.7357

Run times varied dramatically. Thread 1, for example, which was decomposing the same integer
998 each time, and performing the same file I/O each time, took only 0.0030 seconds in one
sample, but 3.0784 seconds in another. That is over a 1000x variation in thread run time. It is
likely that thread scheduling or other thread overhead is negatively impacting the performance of
threads in this environment.

______________________________________________________________________________
Copyright © 2011. Arthur (Wesley) Kenzie. All Rights Reserved. Page 6 of 23
BCIT Computing and Information Technology
COMP 8005 Network and Security Applications Development
Due Date: February 1, 2011
Author: Arthur (Wesley) Kenzie A00242330
Assignment 1: Multi-Process versus Multi-Threaded Program Analysis (Final Version)
______________________________________________________________________________

Next the multiple process testing was done, as shown below. Note the command line used to start
this program is exactly the same as for the multiple thread example shown previously, other than
the program name here is ./a1p rather than ./a1t.

It is interesting to note that process scheduling performed by the same Ubuntu Linux 2.6.32-28
kernel is also unpredictable in this VM environment. Processes 1 through 5 are fork()ed in
sequence in threads.c (line 158) and yet they appear in sequence as 2, 3, 5, 4 and then 1.

______________________________________________________________________________
Copyright © 2011. Arthur (Wesley) Kenzie. All Rights Reserved. Page 7 of 23
BCIT Computing and Information Technology
COMP 8005 Network and Security Applications Development
Due Date: February 1, 2011
Author: Arthur (Wesley) Kenzie A00242330
Assignment 1: Multi-Process versus Multi-Threaded Program Analysis (Final Version)
______________________________________________________________________________

Here is a summary of the 5 samples taken for the multiple process Test A. Start times for each
process varied from 0.0008 to 0.0053 seconds, with an average of 0.0019 seconds. This is over
double the average start time of 0.0009 seconds recorded for the multiple thread samples. Total
start times for all processes varied from 0.0050 to 0.0143 seconds, with an average of 0.0094
seconds – again over double the average total start time of 0.0046 seconds for the multiple
thread samples.

Process with 10 file I/O  Process 
Child 1  Child 2  Child 3  Child 4  Child 5  Totals 
loops  averages 

run 1 start times  0.0008  0.0009 0.0010  0.0017 0.0006  0.0010  0.0050


run 2 start times  0.0010  0.0018 0.0038  0.0053 0.0024  0.0029  0.0143
run 3 start times  0.0010  0.0012 0.0010  0.0016 0.0017  0.0013  0.0065
run 4 start times  0.0011  0.0013 0.0012  0.0017 0.0024  0.0015  0.0077
run 5 start times  0.0035  0.0043 0.0015  0.0023 0.0021  0.0027  0.0137
Process average start 
times  0.0015  0.0019 0.0017  0.0025 0.0018  0.0019  0.0094
run 1 run times  0.0065  0.4175 3.1952  0.0028 0.0056  0.7255  3.6276
run 2 run times  0.0031  0.4010 3.1160  0.0032 0.0062  0.7059  3.5295
run 3 run times  0.0016  0.3959 3.1833  0.0032 0.0053  0.7179  3.5893
run 4 run times  0.0018  0.3921 3.1176  0.0041 0.0081  0.7047  3.5237
run 5 run times  0.0018  0.3895 3.1341  0.0077 0.0052  0.7077  3.5383
Process average run 
times  0.0030  0.3992 3.1492  0.0042 0.0061  0.7123  3.5617
Process average total 
times  0.0044  0.4011 3.1509  0.0067 0.0079  0.7142  3.5711

Run times, however, paint a very different picture for processes: they are relatively stable, and
considerably faster than threads. The average for all process run time samples is 0.7123 seconds
compared to 2.1462 seconds for all thread run time samples: approximately 3 times faster. These
averages across all processes/threads, however, actually mask some large disparities. Process 3 is
only marginally faster than Thread 3 on average (run time of 3.1492 vs. 3.1988 seconds).
However, Process 1 is 234 faster than Thread 1 despite doing the exact same work; Process 2 is
6.2 times faster than Thread 2; Process 4 is 330 times faster than Thread 4; and Process 5 is 420
times faster than Thread 5. These are enormous differences in performance.

Since the run times in these test samples make up an average of 99.73% of the total time taken
by processes (0.7123 of total 0.7142 seconds) and an average of 99.96% of the total time taken
by threads (2.1462 of total 2.1471 seconds) the run time advantages of processes are far more
significant in the overall evaluation than the start time advantages of threads.

______________________________________________________________________________
Copyright © 2011. Arthur (Wesley) Kenzie. All Rights Reserved. Page 8 of 23
BCIT Computing and Information Technology
COMP 8005 Network and Security Applications Development
Due Date: February 1, 2011
Author: Arthur (Wesley) Kenzie A00242330
Assignment 1: Multi-Process versus Multi-Threaded Program Analysis (Final Version)
______________________________________________________________________________

Test B (Same as Test A, but with 1000x more file I/O)

The second test was run on the same Xubuntu 10.04 Desktop VM in VMware Workstation on a
Microsoft Windows 7 Ultimate desktop, with the amount of file input/output increased 1000 times.
The intention in this test was to measure the impact of increasing the amount of file input/output
activity, while keeping everything else constant.

An example test run was done on January 30, 2011 at 5:39:07 PST, as shown below. The
command line used to start the multiple processes program was:

./a1p 998 992923727 2050700031 883993838 100939437 --ioloops=5

This will generate 100,000 file input/output operations, rather than the 10 done in Test A.

______________________________________________________________________________
Copyright © 2011. Arthur (Wesley) Kenzie. All Rights Reserved. Page 9 of 23
BCIT Computing and Information Technology
COMP 8005 Network and Security Applications Development
Due Date: February 1, 2011
Author: Arthur (Wesley) Kenzie A00242330
Assignment 1: Multi-Process versus Multi-Threaded Program Analysis (Final Version)
______________________________________________________________________________

Here is a summary of the 5 samples taken for the multiple threaded Test B. Start times for each
thread varied from 0.0004 to 0.0022 seconds, with an average of 0.0008 seconds. Total start
times for all threads varied from 0.0037 to 0.0050 seconds, with an average of 0.0042 seconds.
All of these start times, as expected, were within 10-15% of the start times measured in Test A.

Thread with 100,000  Thread  Thread  Thread 


Thread 1  Thread 4  Thread 5  Totals 
file I/O loops  2  3  averages 

run 1 start times  0.0011  0.0009 0.0007  0.0006 0.0004  0.0007  0.0037


run 2 start times  0.0010  0.0008 0.0006  0.0006 0.0011  0.0008  0.0041
run 3 start times  0.0008  0.0008 0.0007  0.0005 0.0022  0.0010  0.0050
run 4 start times  0.0005  0.0008 0.0005  0.0010 0.0008  0.0007  0.0036
run 5 start times  0.0011  0.0008 0.0007  0.0014 0.0006  0.0009  0.0046
Thread average start 
times  0.0009  0.0008 0.0006  0.0008 0.0010  0.0008  0.0042
run 1 run times  0.5144  0.7985 3.8853  0.5749 0.5576  1.2661  6.3307
run 2 run times  0.7624  0.7624 4.0316  4.0262 4.0591  2.7283  13.6417
run 3 run times  0.2476  0.7075 4.0049  4.0122 4.0230  2.5990  12.9952
run 4 run times  0.5224  3.9509 3.5664  0.5247 0.5067  1.8142  9.0711
run 5 run times  0.4274  4.0277 3.5258  4.0281 0.3810  2.4780  12.3900
Thread average run 
times  0.4948  2.0494 3.8028  2.6332 1.9055  2.1771  10.8857
Thread average total 
times  0.4957  2.0502 3.8034  2.6340 1.9065  2.1780  10.8899
this vs Test A  71.2%  71.1% 118.9%  189.0% 74.4%  101.4%

Run times again varied dramatically. None were as low as the lowest run times measured in Test
A, where 6 run times were measured at less than 0.0100 seconds. In Test B the lowest 6 run
times were all below about 0.52 seconds, which is about 52 times slower.

Oddly, however, Threads 1, 2 and 5 had faster run time averages in Test B than in Test A. These
results make no sense, except in the context of apparent issues with thread scheduling or other
thread overhead impacting the run time performance of threads in this environment.

______________________________________________________________________________
Copyright © 2011. Arthur (Wesley) Kenzie. All Rights Reserved. Page 10 of 23
BCIT Computing and Information Technology
COMP 8005 Network and Security Applications Development
Due Date: February 1, 2011
Author: Arthur (Wesley) Kenzie A00242330
Assignment 1: Multi-Process versus Multi-Threaded Program Analysis (Final Version)
______________________________________________________________________________

Here is a summary of the 5 samples taken for the multiple process Test B. Start times for each
process varied from 0.0006 to 0.0131 seconds, with an average of 0.0040 seconds. This is 5
times the average start time of 0.0008 seconds recorded for the multiple thread samples in Test
B. Total start times for all processes varied from 0.0098 to 0.0315 seconds, with an average of
0.0201 seconds – again about 5 times the average total start time of 0.0042 seconds for the
multiple thread samples in Test B.

These process start times were just over 2 times longer than the process start times in Test A,
which was unexpected, and would require further investigation to understand.

Process with 100,000  Process 
Child 1  Child 2  Child 3  Child 4  Child 5  Totals 
file I/O loops  averages 

run 1 start times  0.0017  0.0013 0.0131 0.0038 0.0101 0.0060  0.0300


run 2 start times  0.0019  0.0029 0.0082 0.0072 0.0113 0.0063  0.0315
run 3 start times  0.0009  0.0007 0.0029 0.0026 0.0027 0.0020  0.0098
run 4 start times  0.0007  0.0006 0.0014 0.0018 0.0100 0.0029  0.0145
run 5 start times  0.0008  0.0008 0.0006 0.0014 0.0112 0.0030  0.0148
Process average start 
times  0.0012  0.0013 0.0052 0.0034 0.0091 0.0040  0.0201
run 1 run times  0.0214  0.4396 3.3315 0.0153 0.0259 0.7667  3.8337
run 2 run times  0.0218  0.4153 3.2627 0.0248 0.0201 0.7489  3.7447
run 3 run times  0.0145  0.4213 3.2047 0.0170 0.0270 0.7369  3.6845
run 4 run times  0.0102  0.4120 3.1892 0.0109 0.0123 0.7269  3.6346
run 5 run times  0.0103  0.3982 3.2068 0.0102 0.0118 0.7275  3.6373
Process average run 
times  0.0156  0.4173 3.2390 0.0156 0.0194 0.7414  3.7070
Process average total 
times  0.0168  0.4185 3.2442 0.0190 0.0285 0.7454  3.7271
this vs Test A  379.3%  104.3% 103.0% 282.7% 359.6% 104.4%

Run time samples for Test B were again relatively stable within each process, as was seen in Test
A. Run times were also longer in Test B across the board, as would be expected. The average
increase in run times resulting from the significant increase in file input/output activity was about
4%.

However, it is not obvious why run time increases were so large for processes 1, 4 and 5 while
being only slightly longer for processes 2 and 3. Further investigation would be required to better
understand these differences.

______________________________________________________________________________
Copyright © 2011. Arthur (Wesley) Kenzie. All Rights Reserved. Page 11 of 23
BCIT Computing and Information Technology
COMP 8005 Network and Security Applications Development
Due Date: February 1, 2011
Author: Arthur (Wesley) Kenzie A00242330
Assignment 1: Multi-Process versus Multi-Threaded Program Analysis (Final Version)
______________________________________________________________________________

Test C (Same as Test A, but with no file I/O)

The third test was again run on the same Xubuntu 10.04 Desktop VM in VMware Workstation on a
Microsoft Windows 7 Ultimate desktop, with no file input/output at all. The intention in this test
was to measure the impact of doing only processor work, with no file or disk activity, while
keeping everything else constant.

An example test run was done on January 30, 2011 at 5:35:58 PST, as shown below. The
command line used to start the multiple processes program was:

./a1p 998 992923727 2050700031 883993838 100939437 --skipfileio

______________________________________________________________________________
Copyright © 2011. Arthur (Wesley) Kenzie. All Rights Reserved. Page 12 of 23
BCIT Computing and Information Technology
COMP 8005 Network and Security Applications Development
Due Date: February 1, 2011
Author: Arthur (Wesley) Kenzie A00242330
Assignment 1: Multi-Process versus Multi-Threaded Program Analysis (Final Version)
______________________________________________________________________________

Here is a summary of the 5 samples taken for the multiple threaded Test C. Start times for each
thread varied from 0.0004 to 0.0029 seconds, with an average of 0.0009 seconds. Total start
times for all threads varied from 0.0031 to 0.0093 seconds, with an average of 0.0047 seconds.
All of these start times, as expected, were within close range of the start times previously
measured in Tests A and B.

Thread  Thread  Thread 


Thread with no file I/O  Thread 1  Thread 4  Thread 5  Totals 
2  3  averages 

run 1 start times  0.0009  0.0007 0.0005  0.0005 0.0005  0.0006  0.0031


run 2 start times  0.0009  0.0007 0.0007  0.0013 0.0006  0.0008  0.0042
run 3 start times  0.0009  0.0007 0.0006  0.0006 0.0006  0.0007  0.0034
run 4 start times  0.0009  0.0008 0.0006  0.0004 0.0010  0.0007  0.0037
run 5 start times  0.0026  0.0029 0.0027  0.0007 0.0004  0.0019  0.0093
Thread average start 
times  0.0012  0.0012 0.0010  0.0007 0.0006  0.0009  0.0047
run 1 run times  0.0029  0.3813 3.4891  0.3823 3.4889  1.5489  7.7445
run 2 run times  0.0026  0.3962 3.6511  3.6518 0.3965  1.6196  8.0982
run 3 run times  0.0023  3.4762 3.0923  3.0932 3.0964  2.5521  12.7604
run 4 run times  0.3901  0.3898 3.4935  3.4949 3.4975  2.2532  11.2658
run 5 run times  0.0016  0.3869 3.5822  3.5860 3.5845  2.2282  11.1412
Thread average run 
times  0.0799  1.0061 3.4616  2.8416 2.8128  2.0404  10.2020
Thread average total 
times  0.0811  1.0072 3.4627  2.8423 2.8134  2.0414  10.2068
this vs Test A  11.5%  34.9% 108.2%  204.0% 109.8%  95.1%

Run times again varied dramatically, but with values quite similar to Test A. There were 4 very
fast run times below 0.0029 seconds, another 7 run times in the range of 0.38 to 0.39 seconds,
and the remaining run times in the range of 3.09 to 3.65 seconds.

Test A produced 6 very fast run times below 0.0093 seconds, another 3 run times at about 0.38
seconds, and all the remaining run times in the range of 3.07 to 3.58 seconds.

Oddly, again, Threads 3, 4 and 5 had slower run time averages in Test C than in Test A, despite
doing less work. These results again make no sense, except in the context of apparent issues with
thread scheduling or other thread overhead impacting the run time performance of threads in this
environment.

______________________________________________________________________________
Copyright © 2011. Arthur (Wesley) Kenzie. All Rights Reserved. Page 13 of 23
BCIT Computing and Information Technology
COMP 8005 Network and Security Applications Development
Due Date: February 1, 2011
Author: Arthur (Wesley) Kenzie A00242330
Assignment 1: Multi-Process versus Multi-Threaded Program Analysis (Final Version)
______________________________________________________________________________

Here is a summary of the 5 samples taken for the multiple process Test C. Start times for each
process varied from 0.0006 to 0.0023 seconds, with an average of 0.0013 seconds. These were
the fastest process start times measured to this point, and were only about 1.4 times slower than
the average 0.0009 second start time for threads in Test C. Total start times for all processes
varied from 0.0056 to 0.0074 seconds, with an average of 0.0063 seconds – about one third
faster than the 0.0094 seconds for processes in Test A, and only 1.3 times slower than the 0.0047
seconds for threads in Test C.

Whether these differences in start times are normal variations, or whether they are impacted by
the amount of file input/output activity performed within each process is a question for further
research. There appears to be evidence for the latter possibility, even if the reasons are not
immediately obvious.

Process 
Process with no file I/O  Child 1  Child 2  Child 3  Child 4  Child 5  Totals 
averages 

run 1 start times  0.0012  0.0013 0.0010 0.0016 0.0023 0.0015  0.0074


run 2 start times  0.0008  0.0008 0.0007 0.0019 0.0017 0.0012  0.0059
run 3 start times  0.0008  0.0008 0.0007 0.0017 0.0020 0.0012  0.0060
run 4 start times  0.0009  0.0008 0.0008 0.0021 0.0020 0.0013  0.0066
run 5 start times  0.0006  0.0006 0.0006 0.0020 0.0018 0.0011  0.0056
Process average start 
times  0.0009  0.0009 0.0008 0.0019 0.0020 0.0013  0.0063
run 1 run times  0.0014  0.3897 3.0755 0.0030 0.0054 0.6950  3.4750
run 2 run times  0.0015  0.3858 3.0408 0.0027 0.0075 0.6877  3.4383
run 3 run times  0.0015  0.3829 3.0963 0.0034 0.0055 0.6979  3.4896
run 4 run times  0.0016  0.3800 3.0473 0.0029 0.0077 0.6879  3.4395
run 5 run times  0.0014  0.3857 3.1460 0.0030 0.0060 0.7084  3.5421
Process average run 
times  0.0015  0.3848 3.0812 0.0030 0.0064 0.6954  3.4769
Process average total 
times  0.0023  0.3857 3.0819 0.0049 0.0084 0.6966  3.4832
this vs Test A  52.7%  96.2% 97.8% 72.3% 105.8% 97.5%

Run time samples for Test C were very stable within each process, pointing to the possibility the
file input/output activity increased the variability in run times. Run times were also mostly shorter
in Test C across the board, as would be expected. The average decrease in run times resulting
from the absence of any file input/output activity was about 2.5% compared to Test A, and about
6% compared to Test B.

______________________________________________________________________________
Copyright © 2011. Arthur (Wesley) Kenzie. All Rights Reserved. Page 14 of 23
BCIT Computing and Information Technology
COMP 8005 Network and Security Applications Development
Due Date: February 1, 2011
Author: Arthur (Wesley) Kenzie A00242330
Assignment 1: Multi-Process versus Multi-Threaded Program Analysis (Final Version)
______________________________________________________________________________

Test D (Same as Test B, but on dedicated server running Ubuntu Server)

The last test in this assignment was run on a dedicated, 8-processor Internet server running 64-
bit Ubuntu 10.04 Server with Linux kernel 2.6.32-27. The intention in this test was to measure
the impact of a more powerful server, while keeping everything else the same as in Test B.

An example test run was done on January 30, 2011 at 16:22:57 EST, as shown below. The
command line used to start the multiple processes program was the same as that in Test B:

./a1p 998 992923727 2050700031 883993838 100939437 --ioloops=5

______________________________________________________________________________
Copyright © 2011. Arthur (Wesley) Kenzie. All Rights Reserved. Page 15 of 23
BCIT Computing and Information Technology
COMP 8005 Network and Security Applications Development
Due Date: February 1, 2011
Author: Arthur (Wesley) Kenzie A00242330
Assignment 1: Multi-Process versus Multi-Threaded Program Analysis (Final Version)
______________________________________________________________________________

Here is a summary of the 5 samples taken for the multiple threaded Test D. Start times for each
thread varied from just 0.0001 to 0.0003 seconds, with an average of 0.0001 seconds. Total start
times for all threads varied from just 0.0006 to 0.0007 seconds, with an average of 0.0006
seconds. These were 7-8 times faster than any of the three previous Tests, which produced
average total start times of 0.0042, 0.0046 and 0.0047 seconds. A more powerful environment
obviously had a significant impact in reducing thread start times.

Thread with 100,000  Thread  Thread  Thread 


Thread 1  Thread 4  Thread 5  Totals 
file I/O loops  2  3  averages 

run 1 start times  0.0002  0.0001 0.0001 0.0001 0.0001 0.0001  0.0006


run 2 start times  0.0002  0.0001 0.0001 0.0001 0.0001 0.0001  0.0006
run 3 start times  0.0003  0.0001 0.0001 0.0001 0.0001 0.0001  0.0007
run 4 start times  0.0002  0.0002 0.0001 0.0001 0.0001 0.0001  0.0007
run 5 start times  0.0002  0.0001 0.0001 0.0001 0.0001 0.0001  0.0006
Thread average start 
times  0.0002  0.0001 0.0001 0.0001 0.0001 0.0001  0.0006
run 1 run times  0.4505  0.4297 2.9049 0.4727 0.4546 0.9425  4.7124
run 2 run times  0.0996  0.4342 2.9073 2.9318 2.9544 1.8655  9.3273
run 3 run times  0.1680  2.9397 2.6254 2.9605 0.1171 1.7621  8.8107
run 4 run times  0.1074  0.4190 2.9005 2.9119 0.4400 1.3558  6.7788
run 5 run times  0.1154  0.4424 2.9040 0.1209 2.9401 1.3046  6.5228
Thread average run 
times  0.1882  0.9330 2.8484 1.8796 1.3812 1.4461  7.2304
Thread average total 
times  0.1884  0.9331 2.8485 1.8797 1.3813 1.4462  7.2310
this vs Test B  38.0%  45.5% 74.9% 71.4% 72.5% 66.4%

Run times again displayed the same tri-level grouping of measurements which has been observed
in all previous thread Tests A, B and C. There were 6 fastest run times in the range of 0.099 to
0.168 seconds, another 8 run times in the range of 0.4190 to 0.4505 seconds, and the remaining
run times in the range of 2.62 to 2.96 seconds. Again, as well, there were large variations
observed in run times for all Threads except for Thread 3. Thread 3 has been observed to
consistently produce the longest run times, for both threads and processes, and it is presumed
that this is caused by the prime number decomposition algorithm for the number 2050700031 in
Thread 3 being the most computationally expensive. The reason for this producing less variability
in thread run times, however, is not known at this time.

______________________________________________________________________________
Copyright © 2011. Arthur (Wesley) Kenzie. All Rights Reserved. Page 16 of 23
BCIT Computing and Information Technology
COMP 8005 Network and Security Applications Development
Due Date: February 1, 2011
Author: Arthur (Wesley) Kenzie A00242330
Assignment 1: Multi-Process versus Multi-Threaded Program Analysis (Final Version)
______________________________________________________________________________

Here is a summary of the 5 samples taken for the multiple process Test D. Start times for each
process were just 0.0002 in 24 of the 25 samples. These were double the start times for the
threads in Test D, but far less than the average 0.0040 second start times for processes in Test B.
Total start times for all processes were just 0.0009 to 0.0010 seconds, which compares favourably
to the 0.0006 to 0.0007 seconds for the threads in Test D, and is 20 times faster than the total
start time average for processes in Test B.

Process with 100,000  Process 
Child 1  Child 2  Child 3  Child 4  Child 5  Totals 
file I/O loops  averages 

run 1 start times  0.0002  0.0002 0.0002 0.0002 0.0002 0.0002  0.0010


run 2 start times  0.0002  0.0002 0.0002 0.0002 0.0002 0.0002  0.0010
run 3 start times  0.0002  0.0002 0.0002 0.0002 0.0002 0.0002  0.0010
run 4 start times  0.0002  0.0002 0.0002 0.0001 0.0002 0.0002  0.0009
run 5 start times  0.0002  0.0002 0.0002 0.0002 0.0002 0.0002  0.0010
Process average start 
times  0.0002  0.0002 0.0002 0.0002 0.0002 0.0002  0.0010
run 1 run times  0.1057  0.3595 2.4899 0.0153 0.0186 0.5978  2.9890
run 2 run times  0.1210  0.3492 2.7298 0.0154 0.0193 0.6469  3.2347
run 3 run times  0.1283  0.3213 2.4767 0.0158 0.0182 0.5921  2.9603
run 4 run times  0.0965  0.3096 2.4551 0.0135 0.0225 0.5794  2.8972
run 5 run times  0.1135  0.3241 3.0586 0.0187 0.0233 0.7076  3.5382
Process average run 
times  0.1130  0.3327 2.6420 0.0157 0.0204 0.6248  3.1239
Process average total 
times  0.1132  0.3329 2.6422 0.0159 0.0206 0.6250  3.1249
this vs Test B  672.2%  79.5% 81.4% 83.8% 72.3% 83.8%

Run times were stable and faster for processes 2, 3, 4 and 5 compared to Test B, which was
expected. Average run time totals were about 16-17% faster than in Test B.

Process 1, however, presented an anomaly with run times consistently and significantly slower
than Test B. Further investigation would be required to determine the possible reasons for this
result.

______________________________________________________________________________
Copyright © 2011. Arthur (Wesley) Kenzie. All Rights Reserved. Page 17 of 23
BCIT Computing and Information Technology
COMP 8005 Network and Security Applications Development
Due Date: February 1, 2011
Author: Arthur (Wesley) Kenzie A00242330
Assignment 1: Multi-Process versus Multi-Threaded Program Analysis (Final Version)
______________________________________________________________________________

Summaries and Conclusions

Four different tests were conducted for this assignment to compare the use of multiple,
concurrent threads versus multiple, concurrent processes. Each of the threads in one program -
and each of the concurrent processes in the other program - performed processor intensive tasks
followed by file input/output intensive tasks that were different from each of the other concurrent
threads and processes. But each thread in one program performed exactly the same tasks as their
corresponding process in the other program, such that the only difference between them was their
implementation in either a thread or a process.

Source code for each of the programs is included on the accompanying DVD for confirmation of
this design.

Timing measurements were done at three places in each program. First, the system time was
recorded just before each thread or each process was started. This time snapshot was passed to
each thread and each process, and used to calculate the “start time” for each thread and each
process, by comparing it to the second timing measurement done as the first step in each thread
and in each process. Finally, the system time was again recorded as the last step in each thread
and in each process, in order to calculate the “run time” - from start to finish - for each thread
and for each process.

These timing measurements showed that the start times for threads is significantly faster than for
processes: between 1.5 and 5 times faster.

However, timing measurements for run times was exactly the opposite, with processes completing
about 2-3 times faster, on average, than threads.

Given that start times in our tests represented much less than 1% of the total time to both start
and finish each thread and each process, the advantage of threads being faster to launch is not
significant, and for all intents and purposes, irrelevant. For threads that can complete their
intended purpose in a very small increment of time, this start up advantage may be useful.
However, in this assignment it was not.

There was evidence that threads in 10-15% of the samples were much faster than in other
samples, and it is presumed that fine tuning of thread scheduling may be possible to provide more
consistent and faster processing times for threads. However, none of the fastest threads
measured were as fast as the fastest processes. Further, the range of timing measurements for
processes was much smaller than for threads, pointing to the likelihood that – at the very least -
process scheduling in the Linux kernels used in this assignment is much more refined and reliable
than thread scheduling.

______________________________________________________________________________
Copyright © 2011. Arthur (Wesley) Kenzie. All Rights Reserved. Page 18 of 23
BCIT Computing and Information Technology
COMP 8005 Network and Security Applications Development
Due Date: February 1, 2011
Author: Arthur (Wesley) Kenzie A00242330
Assignment 1: Multi-Process versus Multi-Threaded Program Analysis (Final Version)
______________________________________________________________________________

Appendix

The following files are included on the accompanying DVD:

/ root directory:
COMP8005_Assignment1_final.docx (this file)
COMP8005_Assignment1_final.doc (doc version of this file)
COMP8005_Assignment1_final.pdf (pdf version of this file)
COMP8005_Assignment1_timing_analysis.xls (Excel spreadsheet timing analysis)
COMP8005_Assignment1_timing_analysis.pdf (pdf version of timing analysis spreadsheet)
Ass1-201101-PTS.pdf (copy of assignment description)
a1p (multiple process executable)
a1t (multiple thread executable)
child*.txt (files created by a1p)
thread*.txt (files created by a1t)
processes.c program listing.pdf (listing of processes.c source code)
threads.c program listing.pdf (listing of threads.c source code)

/src/ directory:
gmp.h (c header file for gmp library)
pthread.h (c header file for pthread library)
multi.c (c source code used as basis for threads.c)
pipe_nonblocking.c (c source code used as basis for processes.c)
primedecompose.c (c source code for decompose() function)
primedecompose.h (c header file for decompose() function)
processes.c (c source code for multiple process program)
threads.c (c source code for multiple thread program)

______________________________________________________________________________
Copyright © 2011. Arthur (Wesley) Kenzie. All Rights Reserved. Page 19 of 23
BCIT Computing and Information Technology
COMP 8005 Network and Security Applications Development
Due Date: February 1, 2011
Author: Arthur (Wesley) Kenzie A00242330
Assignment 1: Multi-Process versus Multi-Threaded Program Analysis (Final Version)
______________________________________________________________________________

The pseudo-code design for processes.c is as follows:

Define prototypes;
Define globals;
Main() function {
Get system time using gettimeofday();
Define variables;
Verify and save command-line arguments;
For ( each child process to be fork()ed ) {
Get system time using gettimeofday();
fork();
if ( child process ) {
do child() function;
}
do parent() function;
}
Get system time using gettimeofday();
Use printf() to display program run time;
Exit;
}

Parent() function {
Return; // do nothing
}

Child() function {
Get system time using gettimeofday();
Calculate and display start time for this process;
Define variables;
Use printf() to display process start time and integer passed to child();
If ( doing prime decomposition ) {
Do calc() with integer passed to child();
}
If ( doing file input/output ) {
Fopen() file in write mode;
For ( number of file i/o loops passed to child() ) {
Do write to file with fputs();
Do read from file with fgets();
}
Fclose() file;
}
Get system time using gettimeofday();
Use printf() to display child process run time;
Exit;
}

Calc() function {
// as per rosettacode.org
}
______________________________________________________________________________
Copyright © 2011. Arthur (Wesley) Kenzie. All Rights Reserved. Page 20 of 23
BCIT Computing and Information Technology
COMP 8005 Network and Security Applications Development
Due Date: February 1, 2011
Author: Arthur (Wesley) Kenzie A00242330
Assignment 1: Multi-Process versus Multi-Threaded Program Analysis (Final Version)
______________________________________________________________________________

The pseudo-code design for threads.c is as follows:

Define prototypes;
Define globals;
Main() function {
Get system time using gettimeofday();
Define variables;
Verify and save command-line arguments;
For ( each thread to be created ) {
Load thread_data_array[] with values to be passed to thread;
Get system time using gettimeofday();
Use pthread_create() to create the next thread and pass thread()
function;
}
Get system time using gettimeofday();
Use printf() to display program run time;
Use pthread_exit() to exit program when all threads are done;
}

Thread() function {
// to be executed by each new thread
Get system time using gettimeofday();
Calculate and display start time for this thread;
Define variables;
Use printf() to display thread start time and integer passed to thread();
If ( doing prime decomposition ) {
Do mutex lock();
Do calc() with integer passed to thread();
Do mutex unlock();
}
If ( doing file input/output ) {
Fopen() file in write mode;
For ( number of file i/o loops passed to thread() ) {
Do write to file with fputs();
Do read from file with fgets();
}
Fclose() file;
}
Get system time using gettimeofday();
Use printf() to display thread run time;
Exit;
}

Calc() function {
// as per rosettacode.org
}

______________________________________________________________________________
Copyright © 2011. Arthur (Wesley) Kenzie. All Rights Reserved. Page 21 of 23
BCIT Computing and Information Technology
COMP 8005 Network and Security Applications Development
Due Date: February 1, 2011
Author: Arthur (Wesley) Kenzie A00242330
Assignment 1: Multi-Process versus Multi-Threaded Program Analysis (Final Version)
______________________________________________________________________________

Bibliography

[1] Xubuntu: Linux for human beings. Reference found on “xubuntu.org” Internet site at
http://www.xubuntu.org/about/ on December 2, 2010.

[2] Ubuntu Server Edition. Reference found on “ubuntu.com” Internet site at


http://www.ubuntu.com/server/ on December 2, 2010.

[3] VMware Workstation. Reference found on “vmware.com” Internet site at


http://www.vmware.com/products/workstation/ on December 2, 2010.

[4] Get to know Windows 7. Reference found on “microsoft.com” Internet site at


http://www.microsoft.com/windows/windows-7/ on December 2, 2010.

[5] Category: Prime Numbers. Reference found on “rosettacode.org” Internet site at


http://rosettacode.org/wiki/Category:Prime_Numbers on January 30, 2011.

[6] YoLinux Tutorial: Fork, Exec and Process Control. Reference found on “yolinux.com” Internet
site at http://yolinux.com/TUTORIALS/ForkExecProcesses.html on January 28, 2011.

[7] Introduction to Parallel Computing. Blaise Barney, Lawrence Livermore National Laboratory.
Reference found on “computing.llnl.gov” Internet site at
https://computing.llnl.gov/tutorials/parallel_comp/ on January 22, 2011.

[8] POSIX Threads Programming. Blaise Barney, Lawrence Livermore National Laboratory.
Reference found on “computing.llnl.gov” Internet site at
https://computing.llnl.gov/tutorials/pthreads/ on January 22, 2011.

[9] The GNU Multiple Precision Arithmetic Library. Reference found on “gmplib.org” Internet site
at http://gmplib.org/ on January 22, 2011.

______________________________________________________________________________
Copyright © 2011. Arthur (Wesley) Kenzie. All Rights Reserved. Page 22 of 23
BCIT Computing and Information Technology
COMP 8005 Network and Security Applications Development
Due Date: February 1, 2011
Author: Arthur (Wesley) Kenzie A00242330
Assignment 1: Multi-Process versus Multi-Threaded Program Analysis (Final Version)
______________________________________________________________________________

Credits

Xubuntu is a registered trademark of Canonical Ltd.


Ubuntu is a registered trademark of Canonical Ltd.
VMware is a registered trademark of VMware Inc.
Windows is a registered trademark of Microsoft Corporation.
Linux is a registered trademark of Linus Torvalds.
Rosetta Code algorithm provided under GNU Free Documentation License 1.2.
GNU Multi-Precision library provided under GNU Lesser General Public License.
multi.c and pipe_nonblocking.c are Copyright (c) 2001 Aman Abdulla.

______________________________________________________________________________
Copyright © 2011. Arthur (Wesley) Kenzie. All Rights Reserved. Page 23 of 23
COMP 8005, Assignment 1 January 2011

A B C D E F G H I
1 Test A
2
file I/O loops in each Process 
10 10 10 10 10
3 or Thread ...
4
Process 
Process
Process with 10 file I/O  Process 
Child 1 Child 2 Child 3 Child 4 Child 5 Totals Totals vs 
loops averages
5 Threads
6 run 1 start times 0.0008 0.0009 0.0010 0.0017 0.0006 0.0010 0.0050 87.7%
7 run 2 start times 0.0010 0.0018 0.0038 0.0053 0.0024 0.0029 0.0143 366.7%
8 run 3 start times 0.0010 0.0012 0.0010 0.0016 0.0017 0.0013 0.0065 151.2%
9 run 4 start times 0.0011 0.0013 0.0012 0.0017 0.0024 0.0015 0.0077 145.3%
10 run 5 start times 0.0035 0.0043 0.0015 0.0023 0.0021 0.0027 0.0137 342.5%
11 Process average start times 0.0015 0.0019 0.0017 0.0025 0.0018 0.0019 0.0094 203.4%
12 run 1 run times 0.0065 0.4175 3.1952 0.0028 0.0056 0.7255 3.6276 22.9%
13 run 2 run times 0.0031 0.4010 3.1160 0.0032 0.0062 0.7059 3.5295 36.3%
14 run 3 run times 0.0016 0.3959 3.1833 0.0032 0.0053 0.7179 3.5893 27.3%
15 run 4 run times 0.0018 0.3921 3.1176 0.0041 0.0081 0.7047 3.5237 51.7%
16 run 5 run times
run 5 run times 0 0018
0.0018 0 3895
0.3895 3 1341
3.1341 0 0077
0.0077 0 0052
0.0052 0 7077
0.7077 3 5383
3.5383 43 3%
43.3%
17 Process average run times 0.0030 0.3992 3.1492 0.0042 0.0061 0.7123 3.5617 33.2%
18 Process average total times 0.0044 0.4011 3.1509 0.0067 0.0079 0.7142 3.5711 33.3%
19
Thread 
Thread with 10 file I/O  Thread 
Thread 1 Thread 2 Thread 3 Thread 4 Thread 5 Totals Totals vs 
loops averages
20 Processes
21 run 1 start times 0.0021 0.0011 0.0005 0.0009 0.0011 0.0011 0.0057 114.0%
22 run 2 start times 0.0010 0.0008 0.0006 0.0004 0.0011 0.0008 0.0039 27.3%
23 run 3 start times 0.0009 0.0009 0.0006 0.0004 0.0015 0.0009 0.0043 66.2%
24 run 4 start times 0.0010 0.0009 0.0007 0.0006 0.0021 0.0011 0.0053 68.8%
25 run 5 start times 0.0009 0.0007 0.0006 0.0013 0.0005 0.0008 0.0040 29.2%
26 Thread average start times 0.0012 0.0009 0.0006 0.0007 0.0013 0.0009 0.0046 49.2%
27 run 1 run times 3.0784 3.4788 3.0804 3.0858 3.0845 3.1616 15.8079 435.8%
28 run 2 run times 0.0030 3.4893 3.1106 0.0045 3.1092 1.9433 9.7166 275.3%
29 run 3 run times 0.0032 3.4758 3.0950 3.4775 3.0997 2.6302 13.1512 366.4%
30 run 4 run times 0.0040 3.5864 3.2055 0.0093 0.0080 1.3626 6.8132 193.4%
31 run 5 run times 0.3874 0.3855 3.5024 0.3860 3.5050 1.6333 8.1663 230.8%
32 Thread average run times 0.6952 2.8832 3.1988 1.3926 2.5613 2.1462 10.7310 301.3%
33 Thread average total times
Thread average total times 0 6964
0.6964 2 8840
2.8840 3 1994
3.1994 1 3933
1.3933 2 5625
2.5625 2 1471
2.1471 10 7357
10.7357 300 6%
300.6%
34

Copyright (c) 2011. Arthur (Wesley) Kenzie. All Rights Reserved. Page 1 of 5
COMP 8005, Assignment 1 January 2011

A B C D E F G H I
35 Test B
36
file I/O loops in each Process 
100,000 100,000 100,000 100,000 100,000
37 or Thread ...
38
Process 
Process
Process with 100,000 file  Process 
Child 1 Child 2 Child 3 Child 4 Child 5 Totals Totals vs 
I/O loops averages
39 Threads
40 run 1 start times 0.0017 0.0013 0.0131 0.0038 0.0101 0.0060 0.0300 810.8%
41 run 2 start times 0.0019 0.0029 0.0082 0.0072 0.0113 0.0063 0.0315 768.3%
42 run 3 start times 0.0009 0.0007 0.0029 0.0026 0.0027 0.0020 0.0098 196.0%
43 run 4 start times 0.0007 0.0006 0.0014 0.0018 0.0100 0.0029 0.0145 402.8%
44 run 5 start times 0.0008 0.0008 0.0006 0.0014 0.0112 0.0030 0.0148 321.7%
45 Process average start times 0.0012 0.0013 0.0052 0.0034 0.0091 0.0040 0.0201 479.0%
46 run 1 run times 0.0214 0.4396 3.3315 0.0153 0.0259 0.7667 3.8337 60.6%
47 run 2 run times 0.0218 0.4153 3.2627 0.0248 0.0201 0.7489 3.7447 27.5%
48 run 3 run times 0.0145 0.4213 3.2047 0.0170 0.0270 0.7369 3.6845 28.4%
49 run 4 run times 0.0102 0.4120 3.1892 0.0109 0.0123 0.7269 3.6346 40.1%
50 run 5 run times
run 5 run times 0 0103
0.0103 0 3982
0.3982 3 2068
3.2068 0 0102
0.0102 0 0118
0.0118 0 7275
0.7275 3 6373
3.6373 29 4%
29.4%
51 Process average run times 0.0156 0.4173 3.2390 0.0156 0.0194 0.7414 3.7070 34.1%
52 Process average total times 0.0168 0.4185 3.2442 0.0190 0.0285 0.7454 3.7271 34.2%
53 this vs Test A 379.3% 104.3% 103.0% 282.7% 359.6% 104.4%
54
Thread 
Thread with 100,000 file I/O  Thread 
Thread 1 Thread 2
Thread 1 Thread 2 Thread 3
Thread 3 Thread 4
Thread 4 Thread
Thread 5
5 Totals Totals vs
Totals vs 
loops averages
55 Processes
56 run 1 start times 0.0011 0.0009 0.0007 0.0006 0.0004 0.0007 0.0037 12.3%
57 run 2 start times 0.0010 0.0008 0.0006 0.0006 0.0011 0.0008 0.0041 13.0%
58 run 3 start times 0.0008 0.0008 0.0007 0.0005 0.0022 0.0010 0.0050 51.0%
59 run 4 start times 0.0005 0.0008 0.0005 0.0010 0.0008 0.0007 0.0036 24.8%
60 run 5 start times 0.0011 0.0008 0.0007 0.0014 0.0006 0.0009 0.0046 31.1%
61 Thread average start times 0.0009 0.0008 0.0006 0.0008 0.0010 0.0008 0.0042 20.9%
62 run 1 run times 0.5144 0.7985 3.8853 0.5749 0.5576 1.2661 6.3307 165.1%
63 run 2 run times 0.7624 0.7624 4.0316 4.0262 4.0591 2.7283 13.6417 364.3%
64 run 3 run times 0.2476 0.7075 4.0049 4.0122 4.0230 2.5990 12.9952 352.7%
65 run 4 run times 0.5224 3.9509 3.5664 0.5247 0.5067 1.8142 9.0711 249.6%
66 run 5 run times 0.4274 4.0277 3.5258 4.0281 0.3810 2.4780 12.3900 340.6%
67 Thread average run times
Thread average run times 0 4948
0.4948 2 0494
2.0494 3 8028
3.8028 2 6332
2.6332 1 9055
1.9055 2 1771
2.1771 10 8857
10.8857 293 7%
293.7%
68 Thread average total times 0.4957 2.0502 3.8034 2.6340 1.9065 2.1780 10.8899 292.2%
69 this vs Test A 71.2% 71.1% 118.9% 189.0% 74.4% 101.4%
70

Copyright (c) 2011. Arthur (Wesley) Kenzie. All Rights Reserved. Page 2 of 5
COMP 8005, Assignment 1 January 2011

A B C D E F G H I
71 Test C
72
file I/O loops in each Process 
0 0 0 0 0
73 or Thread ...
74
Process 
Process
Process 
Process with no file I/O Child 1 Child 2 Child 3 Child 4 Child 5 Totals Totals vs 
averages
75 Threads
76 run 1 start times 0.0012 0.0013 0.0010 0.0016 0.0023 0.0015 0.0074 238.7%
77 run 2 start times 0.0008 0.0008 0.0007 0.0019 0.0017 0.0012 0.0059 140.5%
78 run 3 start times 0.0008 0.0008 0.0007 0.0017 0.0020 0.0012 0.0060 176.5%
79 run 4 start times 0.0009 0.0008 0.0008 0.0021 0.0020 0.0013 0.0066 178.4%
80 run 5 start times 0.0006 0.0006 0.0006 0.0020 0.0018 0.0011 0.0056 60.2%
81 Process average start times 0.0009 0.0009 0.0008 0.0019 0.0020 0.0013 0.0063 132.9%
82 run 1 run times 0.0014 0.3897 3.0755 0.0030 0.0054 0.6950 3.4750 44.9%
83 run 2 run times 0.0015 0.3858 3.0408 0.0027 0.0075 0.6877 3.4383 42.5%
84 run 3 run times 0.0015 0.3829 3.0963 0.0034 0.0055 0.6979 3.4896 27.3%
85 run 4 run times 0.0016 0.3800 3.0473 0.0029 0.0077 0.6879 3.4395 30.5%
86 run 5 run times
run 5 run times 0 0014
0.0014 0 3857
0.3857 3 1460
3.1460 0 0030
0.0030 0 0060
0.0060 0 7084
0.7084 3 5421
3.5421 31 8%
31.8%
87 Process average run times 0.0015 0.3848 3.0812 0.0030 0.0064 0.6954 3.4769 34.1%
88 Process average total times 0.0023 0.3857 3.0819 0.0049 0.0084 0.6966 3.4832 34.1%
89 this vs Test A 52.7% 96.2% 97.8% 72.3% 105.8% 97.5%
90
Thread 
Thread 
Thread with no file I/O
Thread with no file I/O Thread 1 Thread 2
Thread 1 Thread 2 Thread 3
Thread 3 Thread 4
Thread 4 Thread 5
Thread 5 Totals Totals vs 
Totals vs
averages
91 Processes
92 run 1 start times 0.0009 0.0007 0.0005 0.0005 0.0005 0.0006 0.0031 41.9%
93 run 2 start times 0.0009 0.0007 0.0007 0.0013 0.0006 0.0008 0.0042 71.2%
94 run 3 start times 0.0009 0.0007 0.0006 0.0006 0.0006 0.0007 0.0034 56.7%
95 run 4 start times 0.0009 0.0008 0.0006 0.0004 0.0010 0.0007 0.0037 56.1%
96 run 5 start times 0.0026
0 00 6 0.0029
0 00 9 0.0027
0 00 0.0007
0 000 0.0004
0 000 0.0019
0 00 9 0.0093
0 0093 166.1%
66 %
97 Thread average start times 0.0012 0.0012 0.0010 0.0007 0.0006 0.0009 0.0047 75.2%
98 run 1 run times 0.0029 0.3813 3.4891 0.3823 3.4889 1.5489 7.7445 222.9%
99 run 2 run times 0.0026 0.3962 3.6511 3.6518 0.3965 1.6196 8.0982 235.5%
100 run 3 run times 0.0023 3.4762 3.0923 3.0932 3.0964 2.5521 12.7604 365.7%
101 run 4 run times 0.3901 0.3898 3.4935 3.4949 3.4975 2.2532 11.2658 327.5%
102 run 5 run times 0.0016 0.3869 3.5822 3.5860 3.5845 2.2282 11.1412 314.5%
103 Th d i
Thread average run times 0.0799 1.0061 3.4616 2.8416 2.8128 2.0404 10.2020 293.4%%
104 Thread average total times 0.0811 1.0072 3.4627 2.8423 2.8134 2.0414 10.2068 293.0%
105 this vs Test A 11.5% 34.9% 108.2% 204.0% 109.8% 95.1%
106

Copyright (c) 2011. Arthur (Wesley) Kenzie. All Rights Reserved. Page 3 of 5
COMP 8005, Assignment 1 January 2011

A B C D E F G H I
107 Test D
108
On dedicated Internet 
server with 8 processors, 
100,000 100,000 100,000 100,000 100,000
and 100,000 file I/O loops 
109 per Process or Thread...
per Process or Thread
110
Process 
Process with 100,000 file  Process 
Child 1 Child 2 Child 3 Child 4 Child 5 Totals Totals vs 
I/O loops averages
111 Threads
112 run 1 start times 0.0002 0.0002 0.0002 0.0002 0.0002 0.0002 0.0010 166.7%
113 run 2 start times 0.0002 0.0002 0.0002 0.0002 0.0002 0.0002 0.0010 166.7%
114 run 3 start times 0.0002 0.0002 0.0002 0.0002 0.0002 0.0002 0.0010 142.9%
115 run 4 start times 0.0002 0.0002 0.0002 0.0001 0.0002 0.0002 0.0009 128.6%
116 run 5 start times 0.0002 0.0002 0.0002 0.0002 0.0002 0.0002 0.0010 166.7%
117 Process average start times 0.0002 0.0002 0.0002 0.0002 0.0002 0.0002 0.0010 153.1%
118 run 1 run times 0.1057 0.3595 2.4899 0.0153 0.0186 0.5978 2.9890 63.4%
119 run 2 run times 0.1210 0.3492 2.7298 0.0154 0.0193 0.6469 3.2347 34.7%
120 run 3 run times
run 3 run times 0 1283
0.1283 0 3213
0.3213 2 4767
2.4767 0 0158
0.0158 0 0182
0.0182 0 5921
0.5921 2 9603
2.9603 33 6%
33.6%
121 run 4 run times 0.0965 0.3096 2.4551 0.0135 0.0225 0.5794 2.8972 42.7%
122 run 5 run times 0.1135 0.3241 3.0586 0.0187 0.0233 0.7076 3.5382 54.2%
123 Process average run times 0.1130 0.3327 2.6420 0.0157 0.0204 0.6248 3.1239 43.2%
124 Process average total times 0.1132 0.3329 2.6422 0.0159 0.0206 0.6250 3.1249 43.2%
125 this vs Test B 672.2% 79.5% 81.4% 83.8% 72.3% 83.8%
126
Thread 
Thread with 100,000 file I/O  Thread 
Thread 1 Thread 2 Thread 3 Thread 4 Thread 5 Totals Totals vs 
loops averages
127 Processes
128 run 1 start times 0.0002 0.0001 0.0001 0.0001 0.0001 0.0001 0.0006 60.0%
129 run 2 start times 0.0002 0.0001 0.0001 0.0001 0.0001 0.0001 0.0006 60.0%
130 run 3 start times 0.0003 0.0001 0.0001 0.0001 0.0001 0.0001 0.0007 70.0%
131 run 4 start times 0.0002 0.0002 0.0001 0.0001 0.0001 0.0001 0.0007 77.8%
132 run 5 start times 0.0002 0.0001 0.0001 0.0001 0.0001 0.0001 0.0006 60.0%
133 Thread average start times 0.0002 0.0001 0.0001 0.0001 0.0001 0.0001 0.0006 65.3%
134 run 1 run times 0.4505 0.4297 2.9049 0.4727 0.4546 0.9425 4.7124 157.7%
135 run 2 run times 0.0996 0.4342 2.9073 2.9318 2.9544 1.8655 9.3273 288.4%
136 run 3 run times 0.1680 2.9397 2.6254 2.9605 0.1171 1.7621 8.8107 297.6%
137 run 4 run times
run 4 run times 0 1074
0.1074 0 4190
0.4190 2 9005
2.9005 2 9119
2.9119 0 4400
0.4400 1 3558
1.3558 6 7788
6.7788 234 0%
234.0%
138 run 5 run times 0.1154 0.4424 2.9040 0.1209 2.9401 1.3046 6.5228 184.4%
139 Thread average run times 0.1882 0.9330 2.8484 1.8796 1.3812 1.4461 7.2304 231.5%
140 Thread average total times 0.1884 0.9331 2.8485 1.8797 1.3813 1.4462 7.2310 231.4%
141 this vs Test B 38.0% 45.5% 74.9% 71.4% 72.5% 66.4%
142

Copyright (c) 2011. Arthur (Wesley) Kenzie. All Rights Reserved. Page 4 of 5
COMP 8005, Assignment 1 January 2011

A B C D E F G H I
143 Summaries (Tests A, B, C)
144
145 average Process start time 0.0024 (sample size 75)
146 average Thread start time 0.0009 (sample size 75)
147 Thread vs Process 37.9%
148
Child /  Child /  Child /  Child /  Child / 
149 Thread 1 Thread 2 Thread 3 Thread 4 Thread 5
150 average Process run time 0.0067 0.4004 3.1565 0.0076 0.0106 (sample size 15 each)
151 average Thread run time 0.4233 1.9795 3.4877 2.2892 2.4265 (sample size 15 each)
152 Thread vs Process 6324.4% 494.4% 110.5% 30067.8% #######
153
154 average Process total time 0.0079 0.4018 3.1590 0.0102 0.0149 (sample size 15 each)
155 average Thread total time 0.4244 1.9805 3.4885 2.2899 2.4275 (sample size 15 each)
156 Thread vs Process 5390.6% 492.9% 110.4% 22464.7% #######
157
158 median Process run time 0.0018 0.3959 3.1460 0.0034 0.0075 (sample size 15 each)
159 median Thread run time 0.2476 0.7985 3.5024 3.0932 3.0997 (sample size 15 each)
160 Thread vs Process
Thread vs Process ####### 201 7%
201.7% 111 3% 90976
111.3% 90976.5%
5% #######
161
variance in Process run 
162 times 0.0001 0.0003 0.0064 0.0000 0.0001 (sample size 15 each)
163 variance in Thread run times 0.6038 2.6307 0.1045 2.8874 2.3663 (sample size 15 each)
164 Thread vs Process ####### ####### 1638.5% ######## #######
165
166 median Process start time 0.0009 0.0009 0.0010 0.0019 0.0023 (sample size 15 each)
167 median Thread start time 0.0009 0.0008 0.0006 0.0006 0.0008 (sample size 15 each)
168 Thread vs Process 100.0% 88.9% 60.0% 31.6% 34.8%
169
variance in Process start 
170 times 0.000001 ####### 0.000012 0.000003 ####### (sample size 15 each)
variance in Thread start 
i i Th d t t
171 times 0.000000 ####### 0.000000 0.000000 ####### (sample size 15 each)
172 Thread vs Process 52.6% 29.5% 2.4% 4.5% 2.1%
173
174 Notes:
175 Numbers above are in seconds, shown to 4 decimal places.
176 Original timings were to 6 decimal point precision: thus some rounding appears.
Prime number  Child /  Child /  Child /  Child /  Child / 
177 decompositions calculated: Thread 1 Thread 2 Thread 3 Thread 4 Thread 5
992923727 =  2050700031 =  883993838 =  100939437 = 
998 = 2 * 499 107 *  3 * 3 * 3 *  2 * 7 * 13 *  3 * 3 * 139 * 
9279661 75951853 157 * 30937 80687
178

Copyright (c) 2011. Arthur (Wesley) Kenzie. All Rights Reserved. Page 5 of 5
1 /*********************************************************************
2  * Author and Copyright (c) A. Abdulla, January 2001
3  * Original program name: pipe_nonblocking.c
4  * Modified program name: processes.c
5  * Modified by: Arthur (Wesley) Kenzie (BCIT Student ID A00242330)
6  * Modified date: January 28, 2011
7  * Latest version: 1.07a
8  * Description: this program is adapted to demonstrate 3‐9 processes
9  * to be compared to 3‐9 threads in the separate threads.c program
10  * for Assignment 1 in COMP 8005
11  * thanks to rosettacode.org/Prime_decomposition#C
12  * uses the GMP (GNU Multiple Precision Library for the computations
13 **********************************************************************/
14 /********************************************************************
15  * compile as follows:
16  * gcc ‐Wall ‐o a1p processes.c primedecompose.c ‐lgmp ‐lm
17  * to link in gmp and math libraries
18 *********************************************************************/
19 /********************************************************************
20  * run as follows:
21  * ./a1p [‐‐debug] [‐‐skipfileio] [‐‐skipcpu] [‐‐ioloops=x] 1 2 3 4 5 6 7 8 9
22  * where 1‐9 are 3‐9 integer numbers
23  * and ‐‐ioloops=x will only be used if ‐‐skipfileio is not included
24  * and x value in ‐‐ioloops= parameter is 10^x loops
25 *********************************************************************/
26
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include </usr/include/gmp.h>
30 #include "primedecompose.h"
31 #include <fcntl.h>
32 #include <string.h>
33 #include <unistd.h>
34 #include <math.h>
35 #include <sys/time.h>
36
37 #define MSGSIZE         16
38 #define MAX_FACTORS 1024
39 #define BASE10          10
40 #define MINNUMS         3
41 #define MAXNUMS         9
42 #define BCOMM           0 // communicate through pipes or not
43
44 /*‐‐‐‐‐‐ Function prototypes ‐‐‐‐‐‐‐‐‐‐*/
45 int parent (int p[], const uint);
46 void child (int p[], const uint, const uint, const long unsigned int, const double);
47 int calc (char *);
48 void fatal (char *);
49
50 /*‐‐‐‐‐‐‐ globals ‐‐‐‐‐‐‐‐‐‐‐‐‐*/
51 int bdebug = 0; // debug mode or not (default no)
52 int bfileio = 1; // do file i/o in thread (default yes)
53 int bcpu = 1; // do cpu computations in thread (default yes)
54 uint ioloops = 1000; // number of file io loops to do in thread (default 10^3)
55 char *msg1 = "Hello World";
56 char *msg2 = "Goodbye World";
57 char errstr[255];
58 int pint;
59 mpz_t dest[MAX_FACTORS]; // must be large enough to hold all the factors!
60
61 int main(int argc, char **argv)
62 {
63     struct timeval ttp;
64     double tt1, tt2, tt3;
65     gettimeofday(&ttp, NULL);
66     tt1 = ttp.tv_sec+(ttp.tv_usec/1000000.0);
67     long unsigned int linum[argc]; // array of integers entered on command line
68     uint n, processcount, childnum;
69     int pfd[argc][2];
70     char * debug_parm = "‐‐debug";
71     char * skipfileio_parm = "‐‐skipfileio";
72     char * skipcpu_parm = "‐‐skipcpu";
73     char * ioloops_parm = "‐‐ioloops=";
74     uint ioloops_len = strlen(ioloops_parm);
75
76     if((argc‐1 < MINNUMS) || (argc‐1 > MAXNUMS))
77     {
78         printf("Usage: %s <%i‐%i integers (>0 and <2B) to be factored>\n", argv[0], MINNUMS, MAXNUMS);
79         exit(1);
80     }
81     if ( bdebug )
82     {
83         printf("debug: %i parameters\n", (argc‐1));
84     }
85     //
86     processcount = 0;
87     for ( n=1; n<argc; n++ )
88     {
89         // ‐‐debug parameter (anywhere) will turn on debugging mode
90         if ( strcmp((char *)argv[n], debug_parm) == 0 )
91         {
92             bdebug = 1;
93             continue;
94         }
95         // ‐‐skipfileio parameter (anywhere) will skip file i/o in threads
96         if ( strcmp((char *)argv[n], skipfileio_parm) == 0 )
97         {
98             bfileio = 0;
99             continue;
100         }
101         // ‐‐skipcpu parameter (anywhere) will skip cpu work in threads
102         if ( strcmp((char *)argv[n], skipcpu_parm) == 0 )
103         {
104             bcpu = 0;
105             continue;
106         }
107         // ‐‐ioloops= parameter (anywhere) will specify number of file i/o loops in threads
108         // where ‐‐ioloops=3 will do 1,000 loops
109         // ‐‐ioloops=5 will do 100,000 loops
110         if ( strncmp((char *)argv[n], ioloops_parm, ioloops_len) == 0 )
111         {
112             ioloops = (int)pow((double)10, (double)strtol(argv[n]+ioloops_len, NULL, BASE10));
113             continue;
114         }
115         processcount++;
116         linum[processcount] = strtol(argv[n], NULL, BASE10);
117         if ( linum[processcount] <= 0 )
118         {
119             printf("Usage: %s <%i‐%i integers (>0 and <2B) to be factored>\n", argv[0], MINNUMS, MAXNUMS);
120             exit(1);
121         }
122     }
123     if ( bdebug )
124     {
125         printf("debug: %i parameters\n", (argc‐1));
126         for ( n=1; n<=processcount; n++ )
127         {
128             printf("debug: integer %i = %li\n", n, linum[n]);
129         }
130         printf("\n");
131     }
132     //
133     for ( childnum=1; childnum<=processcount; childnum++ )
134     {
135         /*‐‐‐‐‐ Open the pipe(s) between child and parent  ‐‐‐‐‐‐‐‐‐‐‐*/
136         sprintf(errstr, "pipe %i call", childnum);
137         if (pipe(pfd[childnum]) < 0)
138         {
139             fatal (errstr);
140         }
141         /*‐‐‐‐ Set the O_NDELAY flag(s) for p[0] ‐‐‐‐‐‐‐‐‐‐‐*/
142         sprintf(errstr, "fcntl %i call", childnum);
143         if (fcntl (pfd[childnum][0], F_SETFL, O_NDELAY) < 0)
144         {
145             fatal (errstr);
146         }
147     }
148     /*‐‐‐‐‐‐‐‐ fork (each child) ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐*/
149     for ( childnum=1; childnum<=processcount; childnum++ )
150     {
151         sprintf(errstr, "fork %i call", childnum);
152         if ( bdebug )
153         {
154             printf( "debug: child %i about to start with %li\n", childnum, linum[childnum] );
155         }
156         gettimeofday(&ttp, NULL);
157         tt2 = ttp.tv_sec+(ttp.tv_usec/1000000.0);
158         switch(fork())
159         {
160             case ‐1:        /* error */
161                 fatal (errstr);
162             case 0:        /* It's the child */
163                 child (pfd[childnum], BCOMM, childnum, linum[childnum], tt2);
164                 printf("child %i finished\n", childnum);
165             default:       /* parent */
166                 pint = parent (pfd[childnum], BCOMM);
167                 //printf("parent finished child %i with %i\n", childnum, pint);
168         }
169     }
170     gettimeofday(&ttp, NULL);
171     tt3 = ttp.tv_sec+(ttp.tv_usec/1000000.0);
172     if ( bdebug )
173     {
174         printf("debug: program finished after %.4lf seconds\n", tt3‐tt1);
175     }
176     exit(0);
177 }
178
179 /*‐‐‐‐‐‐‐ Parent process function ‐‐‐‐‐‐‐*/
180 // parameter int p[2] is array of pipes to and from child process
181 // p[0] is read descriptor of pipe from child
182 // p[1] is write descriptor of pipe to child
183 // parameter const uint bcomm is boolean whether to read messages being sent from child process to parent
184 // returns int 0 if finished successfully
185 // returns int <> 0 if finished unsuccessfully
186 int parent (int p[2], const uint bcomm)
187 {
188     int nread;
189     char buf[MSGSIZE];
190
191     // if not bcomm then nothing happens in this function
192     if ( bcomm )
193     {
194         close (p[1]);    /* close the write descriptor */
195         for (;;)
196         {
197             switch (nread = read(p[0], buf, MSGSIZE))
198             {
199                 case ‐1:
200                 case 0:
201                     if ( bdebug )
202                     {
203                         printf ("debug: (pipe to/with child empty)\n");
204                     }
205                     sleep(0);
206                     break;
207                 default:
208                     if (strcmp (buf, msg2) == 0)
209                     {
210                         printf ("End of conversation with child\n");
211                         return(0);
212                     }
213                     else
214                     {
215                         printf ("MSG = %s\n", buf);
216                     }
217             }
218         }
219     }
220     return(0);
221 }
222
223 /*‐‐‐‐‐‐ Child process function ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐*/
224 // parameter int p[2] is array of pipes to and from parent process
225 // p[0] is read descriptor of pipe from parent
226 // p[1] is write descriptor of pipe to parent
227 // parameter const uint bcomm is boolean to indicate whether child should communicate with parent over pipes
228 // parameter uint childnum is (arbitrary) number of this child process
229 // parameter num is long long unsigned integer to be decomposed by this child process
230 // parameter dtime is double holding time at start of fork which created this child process
231 // returns void
232 // child process kills itself with exit(0) when done
233 void child (int p[2], const uint bcomm, const uint childnum, const long unsigned int num, const double 
dtime)
234 {
235     struct timeval tp;
236     double t1, t2;
237     gettimeofday(&tp, NULL);
238     t1 = tp.tv_sec+(tp.tv_usec/1000000.0);
239     printf("child %i started in %.4lf seconds with: %li\n", childnum, t1‐dtime, num);
240     int icalc;
241     FILE *fp;
242
243     close (p[0]);    /* close the read descriptor */
244
245     char filename[255];
246     char rbuffer[2];
247     char wbuffer[255];
248     char s[255];
249     printf("child %i result: ", childnum);
250     sprintf(s, "%li", num); // this is integer that gets passed to calc()
251     if ( bdebug )
252     {
253         printf("debug: child %i string %s\n", childnum, s);
254     }
255     
256     // do some cpu computation stuff on the integer passed in
257     if ( bcpu )
258     {
259         printf("child %i: ", childnum);
260         icalc = calc(s);
261         printf("\n");
262     }
263
264     // now do some file i/o stuff
265     if ( bfileio )
266     {
267         sprintf(filename, "child%i.txt", childnum);
268         fp = fopen(filename, "w");
269         if ( fp == NULL )
270         {
271             // error
272             printf("error: child %i file error\n", childnum);
273         }
274         else
275         {
276             if ( bdebug )
277             {
278                 printf("debug: child %i file %s initialized\n", childnum, filename);
279             }
280             for ( icalc=0; icalc<ioloops; icalc++ )
281             {
282                 fputs(wbuffer, fp);
283                 fgets(rbuffer, 2, fp);
284             }
285             fclose(fp);
286         }
287     }
288
289     if ( bcomm )
290     {
291         /*‐‐‐ Send final message ‐‐‐‐‐‐‐‐‐‐‐‐*/
292         write (p[1], msg2, MSGSIZE);
293     }
294     gettimeofday(&tp, NULL);
295     t2 = tp.tv_sec+(tp.tv_usec/1000000.0);
296     printf("child %i finished after %.4lf seconds\n", childnum, t2‐t1);
297     exit(0);
298 }
299
300 /* calc function */
301 // thanks to rosettacode.org/Prime_decomposition#C
302 // January 2011
303 int calc(char * s)
304 {
305     mpz_t n;
306     int i, l;
307     mpz_init_set_str(n, s, 10);
308     l = decompose(n, dest);
309
310     for(i=0; i < l; i++)
311     {
312         gmp_printf("%s%Zd", i?" * ":"", dest[i]);
313       mpz_clear(dest[i]);
314     }
315     return EXIT_SUCCESS;
316 }
317
318 /*‐‐‐‐‐‐‐‐‐‐ Error function ‐‐‐‐‐‐*/
319 // returns void
320 // parameter char * is message to be printed before program aborts
321 void fatal (char *s)
322 {
323   perror (s);    /* print error msg and die */
324   exit(1);
325 }
1 /*******************************************************************
2  * Author and Copyright (c) A. Abdulla, January 2001
3  * Original program name: multi.c
4  * Modified program name: threads.c
5  * Modified by: Arthur (Wesley) Kenzie (BCIT Student ID A00242330)
6  * Modified date: January 28, 2011
7  * Latest version: 1.02f
8  * Description: this program is adapted to demonstrate 3‐9 threads
9  * to be compared to 3‐9 processes in the separate processes.c program
10  * for Assignment 1 in COMP 8005
11  * thanks to rosettacode.org/Prime_decomposition#C
12  * uses the GMP (GNU Multiple Precision Library for the computations
13 *********************************************************************/
14 /********************************************************************
15  * compile as follows:
16  * gcc ‐Wall ‐o a1t threads.c primedecompose.c ‐lgmp ‐lpthread ‐lm
17  * to link in gmp, pthread and math libraries
18 *********************************************************************/
19 /********************************************************************
20  * run as follows:
21  * ./a1t [‐‐debug] [‐‐skipfileio] [‐‐skipcpu] [‐‐ioloops=x] 1 2 3 4 5 6 7 8 9
22  * where 1‐9 are 3‐9 integer numbers
23  * and ‐‐ioloops=x will only be used if ‐‐skipfileio is not included
24  * and x value in ‐‐ioloops= parameter is 10^x loops
25 *********************************************************************/
26
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include </usr/include/gmp.h>
30 #include "primedecompose.h"
31 #include <fcntl.h>
32 #include <string.h>
33 #include <unistd.h>
34 #include <math.h>
35 #include <sys/time.h>
36 #include <pthread.h>
37
38 #define _REENTRANT
39 #define DCE_COMPAT
40 #define MAX_FACTORS 1024
41 #define BASE10          10
42 #define MINNUMS         3 // min number of threads
43 #define MAXNUMS         9 // max number of threads
44
45 /*‐‐‐‐‐‐ Function prototypes ‐‐‐‐‐‐‐‐‐‐*/
46 void * calcplusio (void *);
47 void fatal (char *);
48
49 /*‐‐‐‐‐‐‐‐‐‐‐‐ Mutex Variables ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐*/
50 pthread_mutex_t decomposeLock = PTHREAD_MUTEX_INITIALIZER;
51
52 /*‐‐‐‐‐‐‐ globals ‐‐‐‐‐‐‐‐‐‐‐‐‐*/
53 int bdebug = 0; // debug mode or not (default no)
54 int bfileio = 1; // do file i/o in thread (default yes)
55 int bcpu = 1; // do cpu computations in thread (default yes)
56 uint ioloops = 1000; // number of file io loops to do in thread (default 10^3)
57 struct thread_data {
58         int threadnum; // thread number
59         long int linum; // long int to be decomposed
60         int bdebug; // is debug enabled?
61         double dtime; // time at start of pthread_create()
62         int bfileio; // do file I/O in thread?
63         int bcpu; // do cpu computations in thread?
64         uint iloops; // number of file I/O loops in thread
65     };
66 struct thread_data thread_data_array[MAXNUMS]; // passed to each thread
67
68 int main(int argc, char **argv)
69 {
70     struct timeval ttp;
71     double tt1, tt2, tt3;
72     gettimeofday(&ttp, NULL);
73     tt1 = ttp.tv_sec+(ttp.tv_usec/1000000.0); // program start time
74     char errstr[255];
75     long unsigned int linum[argc]; // array of integers entered on command line
76     uint n, threadcount;
77     pthread_t thread[argc];
78     uint threadnum;
79     int pint; // pthread_create() result
80     char * debug_parm = "‐‐debug";
81     char * skipfileio_parm = "‐‐skipfileio";
82     char * skipcpu_parm = "‐‐skipcpu";
83     char * ioloops_parm = "‐‐ioloops=";
84     uint ioloops_len = strlen(ioloops_parm);
85
86     if((argc‐1 < MINNUMS) || (argc‐1 > MAXNUMS))
87     {
88         printf("Usage: %s <%i‐%i integers (>0 and <2B) to be factored>\n", argv[0], MINNUMS, MAXNUMS);
89         exit(1);
90     }
91     //
92     threadcount = 0;
93     for ( n=1; n<argc; n++ )
94     {
95         // ‐‐debug parameter (anywhere) will turn on debugging mode
96         if ( strcmp((char *)argv[n], debug_parm) == 0 )
97         {
98             bdebug = 1;
99             continue;
100         }
101         // ‐‐skipfileio parameter (anywhere) will skip file i/o in threads
102         if ( strcmp((char *)argv[n], skipfileio_parm) == 0 )
103         {
104             bfileio = 0;
105             continue;
106         }
107         // ‐‐skipcpu parameter (anywhere) will skip cpu work in threads
108         if ( strcmp((char *)argv[n], skipcpu_parm) == 0 )
109         {
110             bcpu = 0;
111             continue;
112         }
113         // ‐‐ioloops= parameter (anywhere) will specify number of file i/o loops in threads
114         // where ‐‐ioloops=3 will do 1,000 loops
115         // ‐‐ioloops=5 will do 100,000 loops
116         if ( strncmp((char *)argv[n], ioloops_parm, ioloops_len) == 0 )
117         {
118             ioloops = (int)pow((double)10, (double)strtol(argv[n]+ioloops_len, NULL, BASE10));
119             continue;
120         }
121         threadcount++;
122         linum[threadcount] = strtol(argv[n], NULL, BASE10);
123         if ( linum[threadcount] <= 0 )
124         {
125             printf("Usage: %s <%i‐%i integers (>0 and <2B) to be factored>\n", argv[0], MINNUMS, MAXNUMS);
126             exit(1);
127         }
128     }
129     if ( bdebug )
130     {
131         printf("debug: %i parameters\n", (argc‐1));
132         for ( n=1; n<=threadcount; n++ )
133         {
134             printf("debug: integer %i = %li\n", n, linum[n]);
135         }
136         printf("\n");
137     }
138    
139     /* ‐‐‐‐‐‐‐‐‐ create each thread ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ */
140     for ( threadnum=1; threadnum<=threadcount; threadnum++ )
141     {
142         sprintf( errstr, "error: pthread_create %i call", threadnum );
143         if ( bdebug )
144         {
145             printf( "debug: thread %i about to start with %li\n", threadnum, linum[threadnum] );
146         }
147         thread_data_array[threadnum].threadnum = threadnum;
148         thread_data_array[threadnum].linum = linum[threadnum];
149         thread_data_array[threadnum].bdebug = bdebug;
150         thread_data_array[threadnum].bfileio = bfileio;
151         thread_data_array[threadnum].iloops = ioloops;
152         thread_data_array[threadnum].bcpu = bcpu;
153         gettimeofday(&ttp, NULL);
154         tt2 = ttp.tv_sec+(ttp.tv_usec/1000000.0);
155         thread_data_array[threadnum].dtime = tt2;
156         pint = pthread_create( &thread[threadnum], NULL, calcplusio, (void *) &thread_data_array[threadnum]
 );
157         if ( pint )
158         {
159             fatal( errstr );
160         }
161     }
162     
163     gettimeofday(&ttp, NULL);
164     tt3 = ttp.tv_sec+(ttp.tv_usec/1000000.0);
165     if ( bdebug )
166     {
167         printf("debug: program finished after %.4lf seconds\n", tt3‐tt1);
168     }
169     pthread_exit(0); // will wait for all threads to finish before exiting
170 }
171
172 /* calcplusio function */
173 // thanks to rosettacode.org/Prime_decomposition#C
174 // based on calc() function
175 // returns void (since this is a thread(ed) function)
176 // parameter td is thread_array struct with thread data
177 // January 2011
178 void * calcplusio(void * td)
179 {
180     struct timeval tp;
181     double t1, t2;
182     gettimeofday(&tp, NULL);
183     t1 = tp.tv_sec+(tp.tv_usec/1000000.0);
184     struct thread_data *parm;
185     parm = (struct thread_data *) td;
186     printf("thread %i started in %.4lf seconds with: %li\n", parm‐>threadnum, t1‐parm‐>dtime, parm‐>linum );
187
188     mpz_t n;
189     int i, l;
190     mpz_t dest[MAX_FACTORS]; // must be large enough to hold all the factors!
191     FILE *fp;
192     char rbuffer[2];
193     char wbuffer[255];
194     char filename[255];
195     char s[255];
196     sprintf(s, "%li", parm‐>linum);
197     if ( parm‐>bdebug )
198     {
199         printf("debug: thread %i string %s\n", parm‐>threadnum, s);
200     }
201
202     // do some cpu computation stuff on the integer passed in
203     if ( parm‐>bcpu )
204     {
205         mpz_init_set_str(n, s, 10);
206         pthread_mutex_lock( &decomposeLock );
207         l = decompose(n, dest);
208         pthread_mutex_unlock( &decomposeLock );
209         printf("thread %i: ", parm‐>threadnum);
210         for( i=0; i < l; i++ )
211         {
212             gmp_printf("%s%Zd", i?" * ":"", dest[i]);
213             mpz_clear(dest[i]);
214         }
215         printf("\n");
216     }
217
218     // now do some file i/o stuff
219     if ( parm‐>bfileio )
220     {
221         sprintf(filename, "thread%i.txt", parm‐>threadnum);
222         sprintf(wbuffer, "%li", parm‐>linum); // write buffer
223         fp = fopen(filename, "w");
224         if ( fp == NULL )
225         {
226             // error
227             printf("error: thread %i file %s could not be created\n", parm‐>threadnum, filename);
228         }
229         else
230         {
231             if ( bdebug )
232             {
233                 printf("\ndebug: thread %i file %s initialized\n", parm‐>threadnum, filename);
234             }
235             for ( i=0; i<(parm‐>iloops); i++ )
236             {
237                 //pthread_mutex_lock( &fputsLock );
238                 fputs(wbuffer, fp);
239                 //pthread_mutex_unlock( &fputsLock );
240                 //pthread_mutex_lock( &fgetsLock );
241                 fgets(rbuffer, 2, fp);
242                 //pthread_mutex_unlock( &fgetsLock );
243             }
244             fclose(fp);
245         }
246     }
247     gettimeofday(&tp, NULL);
248     t2 = tp.tv_sec+(tp.tv_usec/1000000.0);
249     printf("thread %i finished after %.4lf seconds\n", parm‐>threadnum, t2‐t1);
250
251     pthread_exit((void *) NULL);
252 }
253
254 /*‐‐‐‐‐‐‐‐‐‐ Error function ‐‐‐‐‐‐*/
255 // returns void
256 // parameter char * is message to be printed before program aborts
257 void fatal (char *s)
258 {
259   perror (s);    /* print error msg and die */
260   exit(1);
261 }

You might also like