This is FCFS cpu scheduling algorithm.
void findTurnAroundTime(int processes[], int n, int bt[], int wt[], int tat[])
{
// Calculating turnaround time by adding bt[i] + wt[i]
for (int i = 0; i < n; i++)
tat[i] = bt[i] + wt[i];
}
// Function to calculate average waiting and turn-around
// times.
void findavgTime(int processes[], int n, int bt[], int at[])
{
int wt[n], tat[n];
// Function to find waiting time of all processes
findWaitingTime(processes, n, bt, wt, at);
// Function to find turn around time for all processes
findTurnAroundTime(processes, n, bt, wt, tat);
// Display processes along with all details
cout << "Processes " << " Burst Time " << " Arrival Time "
<< " Waiting Time " << " Turn-Around Time "
<< " Completion Time \n";
int total_wt = 0, total_tat = 0;
for (int i = 0; i < n; i++)
{
total_wt = total_wt + wt[i];
total_tat = total_tat + tat[i];
int compl_time = tat[i] + at[i];
cout << " " << i + 1 << "\t\t" << bt[i] << "\t\t" << at[i] << "\t\t"
<< wt[i] << "\t\t " << tat[i] << "\t\t " << compl_time << endl;
}
cout << "Average waiting time = " << (float) total_wt / (float) n;
cout << "\nAverage turn around time = " << (float) total_tat / (float) n;
}
How are variables like wt and tat connected if they are decleared inside each function?(This is the main question)
full code is working.
How are variables like wt and tat connected if they are decleared inside each function?
wt and tat are defined in findavgTime. (They are defined using a non-standard extension but that's a separate issue).
When findavgTime calls findWaitingTime and findTurnAroundTime, it passes those variables to the functions. The functions don't define them in their function body -- they are defined in the functions by way of function arguments. Since wt and tat are arrays, they decay to a pointer to the first elements of the respective arrays when findWaitingTime and findTurnAroundTime are called. Because of that, any changes made to the variables inside those functions are visible in findavgTime too.
You don't have to use the same variable names in the function arguments. You could use
void findTurnAroundTime(int processes[], int n, int bt[], int wt_here[], int tat_here[])
{
for (int i = 0; i < n; i++)
tat_here[i] = bt[i] + wt_here[i];
}
That won't change the behavior of the program.
Related
I was learning to use pthread with hopes it will help some of the slowest pieces of my code
go a bit faster. I tried to (as a warm-up example) to write a Montecarlo integrator using
threads. I wrote a code that compares three approaches:
Single thread pthread evaluation of the integral with NEVALS integrand evaluations.
Multiple thread evaluation of the integral NTHREADS times each with NEVALS
integrand evaluations.
Multiple threads commited to different cores in my CPU, again totalling NEVALS*NTHREADS
integrand evaluations.
Upon running the fastest per integrand evaluations is the single core, between 2 and 3 times faster than the others. The other two seem to be somewhat equivalent except for the fact that
the CPU usage is very different, the second one spreads the threads across all the (8) cores
in my CPU, while the third (unsurprisingly) concentrates the job in NTHREADS and leaves the rest
unoccupied.
Here is the source:
#include <iostream>
#define __USE_GNU
#include <sched.h>
#include <pthread.h>
#include <thread>
#include <stdlib.h>
#include <math.h>
#include <time.h>
#include <unistd.h>
using namespace std;
double aleatorio(double a, double b){
double r = double(rand())/RAND_MAX;
return a + r * (b - a);
}
double funct(double* a){
return pow(a[0],6);
}
void EstimateBounds(int ndim, double (*f)(double*), double* bounds){
double x[ndim];
for(int i=1;i<=1000;i++){
for(int j=0;j<ndim;j++) x[j] = aleatorio(0,1);
if ( f(x) > bounds[1]) bounds[1] = f(x);
if ( f(x) < bounds[0]) bounds[0] = f(x);
}
}
void Integrate(double (*f)(double*), int ndim, double* integral, int verbose, int seed){
int nbatch = 5000000;
const int maxeval = 25*nbatch;
double x[ndim];
srand(seed);
/// Algorithm to estimate the maxima and minima ///
for(int j=0;j<ndim;j++) x[j] = 0.5;
double bounds[2] = {f(x),f(x)};
EstimateBounds(ndim,f,bounds);
/// Integral initialization ///
int niter = int(maxeval/nbatch);
for(int k=1;k<=niter;k++)
{
double loc_min = bounds[0];
double loc_max = bounds[1];
int count = 0;
for (int i=1; i<=nbatch; i++)
{
for(int j=0;j<ndim;j++) x[j] = aleatorio(0,1);
double y = aleatorio(bounds[0],bounds[1]);
if ( f(x) > loc_max ) loc_max = f(x);
if ( f(x) < loc_min ) loc_min = f(x);
if ( f(x) > y && y > 0 ) count++;
if ( f(x) < y && y < 0 ) count--;
}
double delta = (bounds[1]-bounds[0])*double(count)/nbatch;
integral[0] += delta;
integral[1] += pow(delta,2);
bounds[0] = loc_min;
bounds[1] = loc_max;
if(verbose>0){
cout << "Iteration["<<k<<"]: " << k*nbatch;
cout << " integrand evaluations so far" <<endl;
if(verbose>1){
cout << "The bounds for this iteration were = ["<<bounds[0]<<","<<bounds[1]<<"]"<<endl;}
cout << "Integral = ";
cout << integral[0]/k << " +- ";
cout << sqrt((integral[1]/k - pow(integral[0]/k,2)))/(k) << endl;
cout << endl;
}
}
integral[0] /= niter;
integral[1] = sqrt((integral[1]/niter - pow(integral[0],2)))/niter;
}
struct IntegratorArguments{
double (*Integrand)(double*);
int NumberOfVariables;
double* Integral;
int VerboseLevel;
int Seed;
};
void LayeredIntegrate(IntegratorArguments IA){
Integrate(IA.Integrand,IA.NumberOfVariables,IA.Integral,IA.VerboseLevel,IA.Seed);
}
void ThreadIntegrate(void * IntArgs){
IntegratorArguments *IA = (IntegratorArguments*)IntArgs;
LayeredIntegrate(*IA);
pthread_exit(NULL);
}
#define NTHREADS 5
int main(void)
{
cout.precision(16);
bool execute_single_core = true;
bool execute_multi_core = true;
bool execute_multi_core_2 = true;
///////////////////////////////////////////////////////////////////////////
///
/// Single Thread Execution
///
///////////////////////////////////////////////////////////////////////////
if(execute_single_core){
pthread_t thr0;
double integral_value0[2] = {0,0};
IntegratorArguments IntArg0;
IntArg0.Integrand = funct;
IntArg0.NumberOfVariables = 2;
IntArg0.VerboseLevel = 0;
IntArg0.Seed = 1;
IntArg0.Integral = integral_value0;
int t = time(NULL);
cout << "Now Attempting to create thread "<<0<<endl;
int rc0 = 0;
rc0 = pthread_create(&thr0, NULL, ThreadIntegrate,&IntArg0);
if (rc0) {
cout << "Error:unable to create thread," << rc0 << endl;
exit(-1);
}
else cout << "Thread "<<0<<" has been succesfuly created" << endl;
pthread_join(thr0,NULL);
cout << "Thread 0 has finished, it took " << time(NULL)-t <<" secs to finish" << endl;
cout << "Integral Value = "<< integral_value0[0] << "+/-" << integral_value0[1] <<endl;
}
////////////////////////////////////////////////////////////////////////////////
///
/// Multiple Threads Creation
///
///////////////////////////////////////////////////////////////////////////////
if(execute_multi_core){
pthread_t threads[NTHREADS];
double integral_value[NTHREADS][2];
IntegratorArguments IntArgs[NTHREADS];
int rc[NTHREADS];
for(int i=0;i<NTHREADS;i++){
integral_value[i][0]=0;
integral_value[i][1]=0;
IntArgs[i].Integrand = funct;
IntArgs[i].NumberOfVariables = 2;
IntArgs[i].VerboseLevel = 0;
IntArgs[i].Seed = i;
IntArgs[i].Integral = integral_value[i];
}
int t = time(NULL);
for(int i=0;i<NTHREADS;i++){
cout << "Now Attempting to create thread "<<i<<endl;
rc[i] = pthread_create(&threads[i], NULL, ThreadIntegrate,&IntArgs[i]);
if (rc[i]) {
cout << "Error:unable to create thread," << rc[i] << endl;
exit(-1);
}
else cout << "Thread "<<i<<" has been succesfuly created" << endl;
}
/// Thread Waiting Phase ///
for(int i=0;i<NTHREADS;i++) pthread_join(threads[i],NULL);
cout << "All threads have now finished" <<endl;
cout << "This took " << time(NULL)-t << " secs to finish" <<endl;
cout << "Or " << (time(NULL)-t)/NTHREADS << " secs per core" <<endl;
for(int i = 0; i < NTHREADS; i++ ) {
cout << "Thread " << i << " has as the value for the integral" << endl;
cout << "Integral = ";
cout << integral_value[i][0] << " +- ";
cout << integral_value[i][1] << endl;
}
}
////////////////////////////////////////////////////////////////////////
///
/// Multiple Cores Execution
///
///////////////////////////////////////////////////////////////////////
if(execute_multi_core_2){
cpu_set_t cpuset;
CPU_ZERO(&cpuset);
pthread_t threads[NTHREADS];
double integral_value[NTHREADS][2];
IntegratorArguments IntArgs[NTHREADS];
int rc[NTHREADS];
for(int i=0;i<NTHREADS;i++){
integral_value[i][0]=0;
integral_value[i][1]=0;
IntArgs[i].Integrand = funct;
IntArgs[i].NumberOfVariables = 2;
IntArgs[i].VerboseLevel = 0;
IntArgs[i].Seed = i;
IntArgs[i].Integral = integral_value[i];
}
int t = time(NULL);
for(int i=0;i<NTHREADS;i++){
cout << "Now Attempting to create thread "<<i<<endl;
rc[i] = pthread_create(&threads[i], NULL, ThreadIntegrate,&IntArgs[i]);
if (rc[i]) {
cout << "Error:unable to create thread," << rc[i] << endl;
exit(-1);
}
else cout << "Thread "<<i<<" has been succesfuly created" << endl;
CPU_SET(i, &cpuset);
}
cout << "Now attempting to commit different threads to different cores" << endl;
for(int i=0;i<NTHREADS;i++){
const int set_result = pthread_setaffinity_np(threads[i], sizeof(cpu_set_t), &cpuset);
if(set_result) cout << "Error: Thread "<<i<<" could not be commited to a new core"<<endl;
else cout << "Thread reassignment succesful" << endl;
}
/// Thread Waiting Phase ///
for(int i=0;i<NTHREADS;i++) pthread_join(threads[i],NULL);
cout << "All threads have now finished" <<endl;
cout << "This took " << time(NULL)-t << " secs to finish" <<endl;
cout << "Or " << (time(NULL)-t)/NTHREADS << " secs per core" <<endl;
for(int i = 0; i < NTHREADS; i++ ) {
cout << "Thread " << i << " has as the value for the integral" << endl;
cout << "Integral = ";
cout << integral_value[i][0] << " +- ";
cout << integral_value[i][1] << endl;
}
}
pthread_exit(NULL);
}
I compile with
g++ -std=c++11 -w -fpermissive -O3 SOURCE.cpp -lpthread
It seems to me that my threads are actually being excecuted sequentially, because
the time seems to grow with NTHREADS, and it actully takes roughly NTHREADS times longer
than a single thread.
Does anyone have an idea of where the bottleneck is?
You are using rand(), which is a global random number generator. First of all it is not thread-safe, so using it in multiple threads, potentially in parallel, causes undefined behavior.
Even if we set that aside, rand() is using one global instance, shared by all threads. If one thread wants to call it, the processor core needs to check whether the other cores modified its state and needs to refetch that state from the main memory or other caches each time it is used. This is why you observe the drop in performance.
Use the <random> facilities for pseudo-random number generators instead. They offer much better quality random number generators, random number distributions, and the ability to create multiple independent random number generator instances. Make these thread_local, so the threads do not interfere with one another:
double aleatorio(double a, double b){
thread_local std::mt19937 rng{/*seed*/};
return std::uniform_real_distribution<double>{a, b}(rng);
}
Please note though that this is not using proper seeding for std::mt19937, see this question for details and that uniform_real_distribution<double>{a, b} will return a uniformly distributed number between a inclusive and b exclusive. Your original code gave a number between a and b inclusive (potential rounding errors aside). I assume that neither is particularly relevant to you.
Also note my unrelated comments under your question for other things you should improve.
So I've made a basic polynomial class in C++ which stores the coefficients of these polynomials dynamically on the heap. I'm currently in the process of overloading operators so that I can add/subtract polynomials together in order to simplify them etc.
However I'm getting unexpected results when I try to overload the * operator. It looks like instead of returning the value of an index in the array it is returning the position of the array.
This is my *operator method in my .cpp file:
Polynomial Polynomial::operator*(Polynomial p) {
int maxDegree = (degree)+(p.degree - 1);
int *intArray3 = new int[maxDegree];
int i, j;
for (int i = 0; i < degree; i++) {
for (int j = 0; j < p.degree; j++) {
cout << getCoef(i) << " * " << p.getCoef(j) << " = " << getCoef(i)*p.getCoef(j) << endl;
intArray3[j] += (getCoef(i))*(p.getCoef(j));
cout << " intArray3[" << j << "] contains : " << intArray3[j] << endl;
}
}
return Polynomial(maxDegree, intArray3);}
The lines:
cout << getCoef(i) << " * " << p.getCoef(j) << " = " << getCoef(i)*p.getCoef(j) << endl;
and
cout << " intArray3[" << j << "] contains : " << intArray3[j] << endl;
return
10 * 1 = 10
intArray3[0] contains : -842150441
in my console. I'm assuming that the problem lies with my use of pointers somewhere but I can't for the life of me think why. I implemented this overload in a similar way to my + and - overloads and they work fine. Any assistance would be greatly appreciated. Cheers.
I'm having a problem where the objects in my array are lost when I pass the array through a constructor. My first guess was that I needed to change it to an array of pointers but that resulted in a segfault. My next guess was that I needed to copy the array data after passing it but that also didn't work. Here's the problem code:
Universe Object:
class Universe {
public:
Star stars[]; int starsLength;
Planet planets[]; int planetsLength;
public:
Universe(Star st[], int stl, Planet pl[], int pll) {
stars < st; starsLength = stl;
planets < pl; planetsLength = pll;
}
Universe() {
}
public:
void render() {
for(int i = 0;i < starsLength;i++) {
//std::cout << "STAR: " << stars[i].location.x << "," << stars[i].location.y << " " << stars[i].size << " " << stars[i].color.r << "," << stars[i].color.g << "," << stars[i].color.b << "\n";
renderCircle(stars[i].location, stars[i].size, stars[i].color);
}
for(int i = 0;i < planetsLength;i++) {
renderCircle(planets[i].location, planets[i].size, planets[i].color);
}
}
void renderCircle(Point location, float size, Color color) {
glBegin(GL_LINES);
glColor3f(color.r,color.g,color.b);
glVertex2f(location.x+size, location.y+size);
glVertex2f(location.x-size, location.y-size);
glVertex2f(location.x-size, location.y+size);
glVertex2f(location.x+size, location.y-size);
glEnd();
}
};
Method that creates the Universe and gives it the array:
Universe buildUniverse(int size, int seed) {
Point bounds = Point{static_cast <float> (size),static_cast <float> (size)}; //0,0 to size,size
int starCount = min(size/10,random(size/5));
int planetCount = min(size/3,random(size));
Star stars[starCount];
Planet planets[planetCount];
//std::cout << "-- Created " << starCount << " stars and " << planetCount << " planets...\n";
for(int i = 0;i < starCount;i++) {
Point location = {random(bounds.x),random(bounds.y)};
Point velocity = {random(bounds.x/100.0f),random(bounds.y/100.0f)};
float size = random(bounds.x/100.0f);
float mass = random(size*(random(1.0f)+0.5f));
Color color = {1.0f,1.0f,1.0f};
stars[i].setStar(location,velocity,size,mass,color);
}
for(int i = 0;i < planetCount;i++) {
Point location = {random(bounds.x),random(bounds.y)};
Point velocity = {random(bounds.x/100.0f),random(bounds.y/100.0f)};
float size = random(bounds.x/100.0f);
float mass = random(size*(random(1.0f)+0.5f));
Color color = {random(1.0f),random(1.0f),random(1.0f)};
planets[i].setPlanet(location,velocity,size,mass,color);
}
Universe uni = {stars, starCount, planets, planetCount};
std::cout << "Star in array: " << stars[0].location.x << "," << stars[0].location.y << " " << stars[0].size << " " << stars[0].color.r << "," << stars[0].color.g << "," << stars[0].color.b << "\n";
std::cout << "Star passed to uni in an array: " << uni.stars[0].location.x << "," << uni.stars[0].location.y << " " << uni.stars[0].size << " " << uni.stars[0].color.r << "," << uni.stars[0].color.g << "," << uni.stars[0].color.b << "\n";
return uni;
}
Output of of the program:
Building universe...
Star in array: 39.922,39.155 0.167611 1,1,8.85715e-39
Star passed to uni in an array: 7.00649e-45,2.24208e-44 0.0282954 5.90446e-39,1.4013e-45,1.4013e-45
Initializing threaded renderer...
Starting simulation...
What am I doing wrong?
First, your code is not valid C++. Declaring empty arrays using [] does not exist in C++.
So the first thing is to turn this into valid C++ that still preserves what you're trying to accomplish. One solution is to use std::vector:
#include <vector>
class Universe {
public:
std::vector<Star> stars;
std::vector<Planet> planets;
public:
Universe(const std::vector<Star>& st,
const std::vector<Planet>& pl) : stars(st), planets(pl) {}
};
Note the replacement of the non-C++ code with std::vector. Also note that we initialize the vectors using the initializer-list.
Last, note that we no longer need to keep the sizes as separate member variables. Why? Because a vector knows its size by calling the vector::size() member function. For example:
for(int i = 0;i < starsLength;i++) {
can be replaced with
for(int i = 0;i < stars.size();i++) {
In your buildUniverse function, use the following changes:
Universe buildUniverse(int size, int seed) {
Point bounds = Point{static_cast <float> (size),static_cast <float> (size)}; //0,0 to size,size
int starCount = min(size/10,random(size/5));
int planetCount = min(size/3,random(size));
std::vector<Star> stars(starCount);
std::vector<Planet> planets(planetCount);
//...
Universe uni(stars, planets);
The rest of the code stays the same. Now, if after the call to create the Universe, you see that the vectors didn't pass the correct information, then look further. The code above conforms to "normal" C++, such that we can go further and figure out the issue.
I am tasked with two programs and this is the second one. The first program involved no calculation() function and to time the program when it started and finished. My computer will display anything from .523 seconds to .601 seconds.
The second task was to create an inline function for the calculation and I believe that I have done it wrong because it is not faster. I am not sure if I made the calculation function right because it includes display information, or if the inline function should focus only on the multiplication. Either way pulling the arrays out of main and into a function is not faster.
Is the compiler just ignoring it?
#include <ctime>
#include <iostream>
using namespace std;
inline int calculation(){
int i;
double result[10000];
double user[10000];
for(i=0; i<10000; i++){
user[i]=i+100;
}
double second[10000];
for(i=0; i<10000; i++){
second[i]=10099-i;
}
for (i = 0; i < 10000; i++){
result[i] = user[i] * second[i];
}
for (i = 0; i < 10000; i++){
cout << user[i] << " * " << second[i] << " = " << result[i] << '\n';
}
}
int main() {
time_t t1 = time(0); // get time now
struct tm * now = localtime( & t1 );
cout << "The time now is: ";
cout << now->tm_hour << ":" << now->tm_min << ":" << now->tm_sec << endl;
clock_t t; // get ticks
t = clock();
cout << " Also calculating ticks...\n"<<endl;
calculation(); // inline function
time_t t2 = time(0); // get time now
struct tm * now2 = localtime( & t2 );
cout << "The time now is: ";
cout << now2->tm_hour << ":" << now2->tm_min << ":" << now2->tm_sec << endl;
time_t t3= t2-t1;
cout << "This took me "<< t3 << " second(s)" << endl; // ticks
t = clock() - t;
float p;
p = (float)t/CLOCKS_PER_SEC;
cout << "Or more accuratley, this took " << t << " clicks"
<< " or " << p << " seconds"<<endl;
}
Is the compiler just ignoring it?
Most probably, yes. It could be doing that for two reasons:
You're compiling in debug mode. In debug mode all inline keywords are ignored to facilitate debugging.
It's ignoring it because the function is far too long for an inline function, and uses far too much stack space to safely inline, and is only invoked once. The inline keyword is a compiler HINT, not a mandatory requirement. It's the programmer's way of recommending the compiler to inline the function, just like a compiler in release mode will frequently inline functions on its own to increase performance. If it only sees negative value it won't comply.
Also, given the single invocation, it's highly unlikely that you'll even see differences no matter if it works or not. A single native function call is much easier on the CPU than a single task switch at the OS level.
You should disable optimization to verify if what you do has any effect, because there are good chances that the compiler is already inlining the function by itself.
Also, if you want to know exactly what your code does, you should compile with the -s flag in g++, and look at the assembly generated by the compiler for your program. This will remove all uncertainty about what the compiler is doing to your program.
I would not make the function inlined and define arrays as static. For example
int calculation(){
int i;
static double result[10000];
static double user[10000];
for(i=0; i<10000; i++){
user[i]=i+100;
}
static double second[10000];
for(i=0; i<10000; i++){
second[i]=10099-i;
}
for (i = 0; i < 10000; i++){
result[i] = user[i] * second[i];
}
for (i = 0; i < 10000; i++){
cout << user[i] << " * " << second[i] << " = " << result[i] << '\n';
}
}
This may be very simple but I am confused!
I am getting segmentation fault when extracting information from a pointer to a pointer. See the cout section in main(). Any help will be appreciated.
Thanks..
Sen
#include <stdlib.h>
#include <iostream>
typedef struct{
int hour;
int minute;
} Time;
Time* GetNextTime(void)
{
Time *p_time = new Time;
return p_time;
}
void GetTime( Time **sometime )
{
int length = 10;
sometime = new Time*[length];
for(int i=0; i<length; i++)
{
sometime[i] = GetNextTime();
sometime[i]->hour = rand()%24 ;
sometime[i]->minute = rand()%60;
std::cout << "Entered times " << sometime[i]->hour << " hour " << sometime[i]->minute << " minutes " << std::endl;
}
}
int main()
{
Time** _time;
GetTime( _time );
//here is the question
// I cant print them from original _time
for( int i=0; i<10; i++)
std::cout << " Print times " << (*_time)[i].hour << " hour " << (*_time)[i].minute << " minutes " << std::endl;
}
You're passing sometime by value, not by reference so it remains uninitialized. Change GetTime to the following:
void GetTime( Time ** &sometime ) //& means pass by reference
Because you're creating an array of pointers, you can use array notation to access them during printing as well.
std::cout << " Print times " << _time[i]->hour << " hour "
<< _time[i]->minute << " minutes " << std::endl;
Unless an argument is explicitly labelled as using a reference it is passed by value in C++. Thus, assigning to sometime in GetTime() has no effect on _time in main().
My strong advice is not to us explict memory allocation but use containers, e.g. std::vector<T>, instead. You'd still need to pass the container by refernence, however.
In main
It should be
Time *_time;
GetTime(&_time)
And then cout should be done with _time instead of *_time