1 The Compiler In this practicum, we will write an actual program to explore the
ID: 3581628 • Letter: 1
Question
1 The Compiler
In this practicum, we will write an actual program to explore the usage of the compiler from the command line. We will also explore the effect of the optimizing stage on code size and execution speed and learn how to measure program performance.
1.1 Writing a Program
In order to tax the CPU, we will have to write a program that performs fairly complex computations in a loop that will be executed many times. We will write a class that will compute the partial sums and limit of the geometric series. The geometric series is the sum
n1
s(n) = Xri . (1)
i=0
s(n) is called a partial sum. The series limit as n depends on the value of r, the ratio.
If |r| < 1, the series converges, and the limit is
. (2)
If r 1 or r < 1, the series diverges, and the partial sums grow towards infinity.
If r = 1, the partial sum sequence alternates between 1 and +1 and the series does not have a limit in the classical sense.
1.1.1 The Class
The series should be represented by a class named GeometricSeries. The class should have a data member for the ratio, an appropriate constructor, and two member functions. The first member function should compute and return the n-th partial sum, using equation (1), taking n as the parameter. You can use the pow() function from the <cmath> header for the exponentiation. See the corresponding man page for its proper usage. The second member function should compute
1
the limit as n approaches infinity, using equation (2) for |r| < 1. In the case of divergence (r 1 or r < 1), the limit member function should return the special IEEE floating point value of infinity(). In the case of r = 1, the limit member function should return the special IEEE floating point value of quiet NaN(). These values can be accessed by using the appropriate static member functions of the std::numeric limits<double> class, which is defined in the <limits> header. Documentation for that header can be found at http://www.cplusplus.com/reference/ std/limits/numeric_limits/. So to return the infinity representation for double, you would write return std::numeric_limits<double>::infinity();
You can safely assume that the Division’s machines implement the IEEE floating point standard and thus skip the detection of the presence of these special values.
When designing the class, choose appropriate names for the member functions and data member. Make sure that you choose proper argument and return types and pay attention to const correctness. As discussed in class, use separate, appropriately named files for the class header and implementation.
In order to tax the CPU, we will have to compute the partial sums to a very high value of n that will potentially exhaust the range of a regular int. To avoid overflow, make sure that you use unsigned long variables where necessary.
1.1.2 The Driver
The driver (i.e. the main() function), should take two values as input via std::cin: the ratio r and the number n of the partial sum. It should then instantiate an object of class GeometricSeries using the ratio and output the value of the partial sum, the value of the limit and the time elapsed in microseconds for the computation of both the partial sum and the limit like this:
jh@cs-stu:~/practicum_3$ ./series
.5
1000000
Partial Sum: 2
Limit: 2
Elapsed: 819033
You can measure the execution time by using the gettimeofday() function from the <sys/time.h> system header. Look up the corresponding man page for information on how to use that function, then call it before and after the computation and use the difference to compute the elapsed mi-
croseconds.
2 Compilation
Use separate compilation to create object files for both the driver and the class. Compile both object files normally as well as with second–level optimization (-O2) and save them to appropriate files. E.g. if your main file is called main.cpp, create a regular, non–optimized object file main.o by using g++ -c main.cpp and create another, optimized object file main.opt.o by using g++ -c main.cpp -o main.opt.o. Create both a non–optimized and optimized executable by linking the corresponding object files using the same naming pattern.
Page 2
3 Measuring Performance
You can now measure performance by running the optimized and non–optimized executables with corresponding input. Values of r = 0.5 and n = 1000000 (one million) are good starting points for the Division’s machines resulting in execution times in the range of one to two seconds. Since you will have to execute the program multiple times in order to get reliable results, you should use input redirection to pass the values to the program. If a file input.txt contains the two values 0.5 1000000, separated by a space on the first line, you can use it as an input argument to the driver by executing
jh2@cs-stu:~/practicum_3$ ./series < input.txt
Partial Sum: 2
Limit: 2
Elapsed: 818783
4 Questions
Use your newly acquired knowledge to answer the following questions. Submit your answers electronically via the Blackboard test. Submit your source code (no object or executable files, please) electronically in a zipped UTF-8 (ASCII) text file using Blackboard’s file attachment facility in assignments.
(2 points) Does optimization increase or decrease the size of the class object file?
1.
(2 points) Does optimization increase or decrease the size of the main object file?
2.
(2 points) Does optimization increase or decrease the execution time?
3.
(2 points) Why are the execution times not identical for subsequent program runs?
(2 points) Based on five consecutive measurements for the non–optimized and optimized executable each, what is the speedup of the optimized code, defined as the ratio of the average runtime of the non–optimized code and the average runtime of the optimized code?
Explanation / Answer
The question is a bit unclear, with equation 2 not there.
I have written the code based on assuming the equation 2 as a/1-r .
Solution program for this question will be as follows --
#include <iostream>
#include <cmath>
#include <limits>
#include <ctime>
#include <sys/time.h>
using namespace std;
class GeometricSeries
{
long ratio;
void SetRatio();
unsigned long FirstSum(int); //for |r|>1
double SeccondSum(); //for |r|<1
GeometricSeries(); //this is the constructor
};
//member function definitions here
void GeometricSeries::SetRatio(int r)
{
ratio = r;
}
GeometricSeries::GeometricSeries(void)
{
std::cout<<"Object is being created"<<endl;
}
double GeometricSeries::FirstSum(long n)
{
//taxing the CPU by doing continous calculations instead of directly using formula for GP calculation.
unsigned long sum=0;
for(long i=0;i<n;i++)
{
sum=sum+pow(ratio,i);
}
return sum;
}
double GeometricSeries::SecondSum()
{
if (ratio < 1 || ratio >= -1)
return 1/(1-ratio); //for |r|<1 and n tending to infinity , this limit equals a/1-r
else
return std::numeric_limits<double>::infinity(); //returning value of infinty for divergence
}
int main() {
GeometricSeries temp;
long size,r;
std::cin>>size>>r; //taking input values of n and r
temp.SetRatio(r); //setting the value of ratio for the object of class created;
if(size > 1000000) //taking n to not be infinity
{
clock_t start, end;
start = clock();
std::cout<<"Partial Sum = "<<temp.FirstSum(size)<<endl;
std::cout<<"Limit = "<<((1-pow(ratio,size))/(1-r))<<endl;
end = clock();
//printing time elapsed in calculation;
std::cout << "Elapsed " << (double(end - start)) << microseconds << ' ';
}
else //n tends to infinity
{
//if n was infinity we get the output as a limit depending on r
//if |r| < 1 we get answer as 1/1-r
//else we get a divergent series with output as infinty
clock_t start, end;
start = clock();
temp.SecondSum();
end = clock();
//printing time elapsed in calculation;
std::cout << "Elapsed " << (double(end - start)) << microseconds << ' ';
}
return 0;
}
************
Go through this program, and try writing your own, accordingly.
2) to compile it , the steps are already given in the question , just follow them.
Does optimization increase or decrease the size of the class object file?
Ans: The object file contains (among others) the machine code after your source has been compiled, but before it is linked. The size of the object file therefore basically depends on the complexity of the code. Hence, the machine code will decrease upon optimization and therefore the size of the class decreases.
Does optimization increase or decrease the size of the main object file?
Ans : The size of the main object also decreases, because the code image of the class will be copied to the compiled source file of main , so as the class object file decreases, so will the main.
Does optimization increase or decrease the execution time?
Ans : optimization will decrease the exeution time, since we're calcutating reslults in one step , instead of large loops.
Related Questions
Navigate
Integrity-first tutoring: explanations and feedback only — we do not complete graded work. Learn more.