SE250:lab-1:Maintainers report
Different ways class did the lab
There were four basic methods people used to measure the addition time:
- Using just one loop with an addition inside - either for or while
- Using two loops, one with an addition inside and another without one - either for or while
- Using two loops, one with a single addition inside and another with two additions inside - either for or while
- Using a nested loop. A for loop inside either a while or for loop.
- The inside loop was timed and the outer was loop used to do many trials to take an average.
For all methods we need to declare two clock_t type variables to calculate the time.
clock_t start, finish;
Everyone ran the timed loop from about 1 million to a billion times (This is shown as the LIMIT variable in the examples). This is because if a smaller number of additions were done, the time taken is very low and is very close to zero.
NOTE: In all examples, i and j are declared as ints. The variables a and b are tested for int, short, long, float and double.
Single loop with addition inside
start = clock(); for ( i = 0; i < LIMIT; i++ ) { a = a + 1; } finish = clock();
Two loops - empty and with addition
start = clock(); for ( i = 0; i < LIMIT; i++ ) { } end = clock();
The loop with addition is the same as the first example.
Two loops - one and two additions
start = clock(); for ( i = 0; i < LIMIT; i++ ) { a = a + 1; b = b + 1; }
The loop with a single addition is the same as the first example.
Nested loops - inside loop timed
NOTE: A person used a nested for loop because of the limit of the type of variable. But this can be avoided by using a different variable for the loop counter from the one used for the addition.
In this example NUM_OF_TRIALS is the number of trials done of LIMIT additions.
double total_time = 0; start = clock(); for ( i = 0; i < NUM_OF_TRIALS; i++ ) { start = clock(); for ( j = 0; j < LIMIT; j++ ){ a = a + 1; } end = clock(); total_time = total_time + ( end - start ); } finish = clock();
To convert total execution time of loops into seconds:
double seconds = (double) (end - start) / (double) CLOCKS_PER_SEC;
Results from the class
A lot of the reports didn’t state the results since many people did not generate proper results, either because they did not finish the lab or because the results are clearly wrong (negative time etc.).
As for people that did have the results:
The typical pattern seems to be:
- Times shorter for the types int, short, long
- Times longer for the types double, floats
- CS Linux server is slower than the lab PCs
- Empty loop takes longer to process than a loop with an addition in it
Here are some examples on what people have found / said:
From: SE250:lab-1:dcho040
Type Int long Short Float Double -------------------------------------- Test1 2346 2334 3011 9074 9397 Test2 2463 2339 3251 9295 9122 Test3 2447 2343 3086 9029 9054 Test4 2337 2373 2981 9056 9053 Test5 2346 2336 2991 9026 9057 -------------------------------------- AVG 2388 2345 3064 9096 9137
From: SE250:lab-1:twon069 1,000,000,000 additions
int - 2.192sec double - 8.262sec float - 8.629sec long - 2.404sec short - 2.583sec
From: SE250:lab-1:gfun006 1,000,000,000 additions
- Time elapsed to execute an int addition command is: 3.649000 seconds - Time elapsed to execute an long addition command is: 3.122000 seconds - Time elapsed to execute an short addition command is: 3.030900 seconds - Time elapsed to execute an float addition command is: 4.826000 seconds - Time elapsed to execute an double addition command is: 4.746000 seconds
Using the linux server to run the code, from: SE250:lab-1:sshi080
* Processing 100,000,000 additions: 1.4800000000 seconds * Processing 500,000,000 additions: 7.4000000000 seconds * Processing 1,000,000,000 additions: 14.7300000000 seconds The calculations took much longer, the 1 billion additions comparison were 6.32 on the local machine and 14.73 seconds on the linux server. It's safe to say that the linux server is much slower.
Empty loop taking longer than the addition loop!, from SE250:lab-1:jham005
double float long int short noop 484 469 391 390 360 375 469 469 391 391 359 391 453 453 390 453 359 390 469 453 391 438 360 407 469 469 391 422 343 390 437 453 406 406 360 391 469 453 390 437 359 391 469 469 391 438 360 390 453 453 391 406 343 375 468 469 390 422 375 391 (CLOCKS_PER_SEC is 1,000)
Recommended method
The best method that we found was using two loops, one empty and other with an addition inside it. We use this because it is very easy to implement and time.
Code:
#include <stdio.h> // time.h is used for the clock() function, clock_t type and the CLOCKS_PER_SEC macro #include <time.h> // LIMIT = how many additions to do = 1 billion #define LIMIT 1000000000 int main ( void ) { // Loop counter, always INT. int n = 0; // Addition variable. Simply changing the data type of this variable, we can test addition times for different data types. double i = 0; // Holds the number of clock ticks elapsed before the start of the loop clock_t t0; // Variables that hold the times for the empty loop and the one with addition, respectively. double empty, full; // Empty loop t0 = clock(); for ( n = 0; n < LIMIT; n++ ) { } // The time taken for the empty loop empty = (double)(clock( ) - t0) / CLOCKS_PER_SEC; // Loop with addition t0 = clock(); for ( n = 0; n < LIMIT; n++ ) { // The addition being timed. NOTE: If a variables' limit is reached, then it's value is reset. i = i + 1; } // The time taken for the loop with addtions full = (double)(clock() - t0) / CLOCKS_PER_SEC; printf( "1 billion times in EMPTY for loop take %f s\n", empty ); printf( "1 billion addition operations in FULL take %f s\n", full ); printf( "1 billion addition operations take %f s\n", full - empty ) ; return 0; }
Results
Windows Vista Enterprise - Cygwin
Level 1 Computer Science Lab (iMac)
int 1 billion times in EMPTY for loop take 2.558000 s 1 billion addition operations in FULL take 2.340000 s 1 billion addition operations take -0.21800 s long 1 billion times in EMPTY for loop take 2.652000 s 1 billion addition operations in FULL take 2.434000 s 1 billion addition operations take -0.218000 s short 1 billion times in EMPTY for loop take 2.402000 s 1 billion addition operations in FULL take 3.619000 s 1 billion addition operations take 1.217000 s float 1 billion times in EMPTY for loop take 2.589000 s 1 billion addition operations in FULL take 3.183000 s 1 billion addition operations take 0.594000 s double 1 billion times in EMPTY for loop take 2.745000 s 1 billion addition operations in FULL take 3.291000 s 1 billion addition operations take 0.546000 s
Mac OS X Leopard - gcc
Level 1 Computer Science Lab (iMac)
int 1 billion times in EMPTY for loop take 2.925953 s 1 billion addition operations in FULL take 2.923014 s 1 billion addition operations take -0.002939 s long 1 billion times in EMPTY for loop take 2.928598 s 1 billion addition operations in FULL take 2.923283 s 1 billion addition operations take -0.005315 s short 1 billion times in EMPTY for loop take 2.924871 s 1 billion addition operations in FULL take 2.920313 s 1 billion addition operations take -0.004558 s float 1 billion times in EMPTY for loop take 2.924885 s 1 billion addition operations in FULL take 3.760510 s 1 billion addition operations take 0.835625 s double 1 billion times in EMPTY for loop take 2.925178 s 1 billion addition operations in FULL take 3.763027 s 1 billion addition operations take 0.837849 s
Conclusions & Discussion
- Overall, Windows Vista seems to be faster with addition compared to Mac OS X (Note that they are both on the same machine)
- But when the time difference (full - empty) is calculated, Mac OS X gives smaller times for int, short and long. The values are about 1000 times smaller! But for the types float and double, Mac OS X gives higher values compared to Vista!
- int and long took the shortest amount of time.
- The weird thing was that on Vista the short type took six times as long as the long data type. One reason for this might be because the limit for the short type is exceeded multiple times. This might have an extra step involved that we don't know about. But on the Mac this did not happen. short actually took less time than long
These results are certainly not what we expected and it is very hard to think about why these things happen. But overall int seems to take the shortest amount of time and float took the longest.
Common Errors, Problems and Misunderstandings
- The main sort of problem that almost everyone had was that their lack of practice of C, starting again after having that 4-5 months break was a challenge.
- Another major problem was syntax errors but this is expected due to the lack of C programming over the holidays.
- People tried using EMACS but encountered some problems mostly because they are unfamiliar with it and had to revert back to Visual Studio. Since this was covered in a recent lecture (6/3/08), this shouldn’t be a problem from now.
- Major error some people got was that they were getting negative values.
- The clock function returning with result as 0 was another error but this was due to the value being too small and when changed to a higher value this error was resolved.
- There was general confusion about the clock function, as in where to place the clock function (whether inside the addition loop or outside it) and what the clock function actually does (gives result in ticks and doesn’t give actual computer time).
Improvements for 2009
- The lab itself for 2009 should be left as it is because this lab is a good revision tool and a good way of getting back into the flow of things in regards to C programming. The lab acts a good start to the course too as it basically reviews some of the key basic properties required for everyday programming like loops, basic syntax etc. It also introduces a new idea of the clock function which is quite interesting and also quite challenging to implement.
- Things that could be changed before the lab could be giving students an introduction to EMACS as this will give them another option other than visual studio and also maybe a revision lecture on C, just generally going over everything like syntax and also an introduction to the clock function. This will save time and also eliminate a large number of errors and problems that maybe encountered.