20145-5SumII_CSC407_assign1.html
CSC 407: Computer Systems II: 2015 Summer II, Assignment #1
Last Modified 2015 July 21Purpose:
To go over issues related to how the compiler and the linker
serve you, the programmer.
Computing
Please ssh into ctilinux1.cstcis.cti.depaul.edu, or use your own Linux machine.
Compiler optimization (45 Points)
Consider the following program.
/* q1.c
*/
#include <stdlib.h>
#include <stdio.h>
#define unsigned int uint
#define LENGTH ((uint) 512*64)
int initializeArray (uint len,
int* intArray
)
{
uint i;
for (i = 0; i < len; i++)
intArray[i] = (rand() % 64);
}
uint countAdjacent (int maxIndex,
int* intArray,
int direction
)
{
uint i;
uint sum = 0;
for (i = 0; i < maxIndex; i++)
if ( ( intArray[i] == (intArray[i+1] + direction) ) &&
( intArray[i] == (intArray[i+2] + 2*direction) )
)
sum++;
return(sum);
}
uint funkyFunction (uint len,
int* intArray
)
{
uint i;
uint sum = 0;
for (i = 0; i < len-1; i++)
if ( (i % 8) == 0x3 )
sum += 7*countAdjacent(len-2,intArray,+1);
else
sum += 17*countAdjacent(len-2,intArray,-1);
return(sum);
}
int main ()
{
int* intArray = (int*)calloc(LENGTH,sizeof(int));
initializeArray(LENGTH,intArray);
printf("funkyFunction() == %d\n",funkyFunction(LENGTH,intArray));
free(intArray);
return(EXIT_SUCCESS);
}
(8 Points) Compile it for profiling but with no extra optimization with:
$ gcc -o q1None -pg q1.c # Compiles q1.c to write q1None to make profile info
$ ./q1None # Runs q1None
$ gprof q1None # Gives profile info on q1None
Be sure to scroll all the way to the top of gprof output!
What are the number of self seconds taken by:
FunctionSelf secondsinitializeBigArray()__________countAdjaceent()__________funkyFunction()__________
(8 Points)
How did it do the operation (i % 8) == 0x3?
Was it done as a modulus (the same as an expensive division, but returns the remainder instead of the quotient) or something else?
Show the assembly language for this C code
using gdb to dissassemble
funkyFunction() of q1None.
Hint: do:
$ gdb q1None
. . .
(gdb) disass funkyFunction
Dump of assembler code for function funkyFunction:
. . .
and then look for the code that sets up the calls to countAdjacent().
The (i % 8) == 0x3 test is done before either countAdjacent() call.
(8 Points) Compile it for profiling but with optimization with:
$ gcc -o q1Compiler -O1 -pg q1.c # Compiles q1.c to write q1Compiler to make profile info
$ ./q1Compiler # Runs q1Compiler
$ gprof q1Compiler # Gives profile info on q1Compiler
What are the number of self seconds taken by:
FunctionSelf secondsinitializeBigArray()__________countAdjacent()__________funkyFunction()__________(8 Points) Use gdb to dissassemble countAdjacent() of both q1None and q1.
20145-5SumII_CSC407_assign1.htmlCSC 407 Computer Systems II.docx
1. 20145-5SumII_CSC407_assign1.html
CSC 407: Computer Systems II: 2015 Summer II, Assignment
#1
Last Modified 2015 July 21Purpose:
To go over issues related to how the compiler and the linker
serve you, the programmer.
Computing
Please ssh into ctilinux1.cstcis.cti.depaul.edu, or use your own
Linux machine.
Compiler optimization (45 Points)
Consider the following program.
/* q1.c
*/
#include <stdlib.h>
#include <stdio.h>
#define unsigned int uint
#define LENGTH ((uint) 512*64)
int initializeArray(uint len,
int* intArray
)
{
uint i;
2. for (i = 0; i < len; i++)
intArray[i] = (rand() % 64);
}
uint countAdjacent (int maxIndex,
int* intArray,
int direction
)
{
uint i;
uint sum = 0;
for (i = 0; i < maxIndex; i++)
if ( ( intArray[i] == (intArray[i+1] + direction) ) &&
( intArray[i] == (intArray[i+2] + 2*direction) )
)
sum++;
return(sum);
}
uint funkyFunction (uint len,
int* intArray
)
{
uint i;
uint sum = 0;
for (i = 0; i < len-1; i++)
if ( (i % 8) == 0x3 )
sum += 7*countAdjacent(len-2,intArray,+1);
else
3. sum += 17*countAdjacent(len-2,intArray,-1);
return(sum);
}
int main ()
{
int* intArray = (int*)calloc(LENGTH,sizeof(int));
initializeArray(LENGTH,intArray);
printf("funkyFunction() ==
%dn",funkyFunction(LENGTH,intArray));
free(intArray);
return(EXIT_SUCCESS);
}
(8 Points) Compile it for profiling but with no extra
optimization with:
$ gcc -o q1None -pg q1.c # Compiles q1.c to write q1None to
make profile info
$ ./q1None # Runs q1None
$ gprof q1None # Gives profile info on q1None
Be sure to scroll all the way to the top of gprof output!
What are the number of self seconds taken by:
FunctionSelf
secondsinitializeBigArray()__________countAdjaceent()______
____funkyFunction()__________
(8 Points)
How did it do the operation (i % 8) == 0x3?
Was it done as a modulus (the same as an expensive
division, but returns the remainder instead of the quotient) or
something else?
Show the assembly language for this C code
4. using gdb to dissassemble
funkyFunction() of q1None.
Hint: do:
$ gdb q1None
. . .
(gdb) disass funkyFunction
Dump of assembler code for function funkyFunction:
. . .
and then look for the code that sets up the calls to
countAdjacent().
The (i % 8) == 0x3 test is done before either
countAdjacent() call.
(8 Points) Compile it for profiling but with optimization
with:
$ gcc -o q1Compiler -O1 -pg q1.c # Compiles q1.c to write
q1Compiler to make profile info
$ ./q1Compiler # Runs q1Compiler
$ gprof q1Compiler # Gives profile info on
q1Compiler
What are the number of self seconds taken by:
FunctionSelf
secondsinitializeBigArray()__________countAdjacent()_______
___funkyFunction()__________(8 Points) Use gdb to
dissassemble countAdjacent() of both q1None and q1Compiler.
Don't try to understand all the code but in general how
5. did the optimizer make q1Compiler's countAdjacent() faster
than q1None's?
Give a specific example by comparing both assembly
codes.
(8 Points) One optimization the compiler may not have
made would be do the two countAdjacent() calls once each
before the loop in funkyFunction(), put them in variables, and
then use those variables in the loop.
Re-write the code this way:
. . .
uint i;
uint sum = 0;
uint countUp = 7*countAdjacent(len-2,intArray,+1);
uint countDn = 17*countAdjacent(len-2,intArray,-1);
for (i = 0; i < len-1; i++)
if ( (i % 8) == 0x3 )
sum += countUp;
else
sum += countDn;
Compile it for profiling again with optimization with:
$ gcc -o q1Programmer -O1 -pg q1.c # Compiles q1.c to write
q1Programmer to make profile info
$ ./q1Programmer # Runs q1Programmer
$ gprof q1Programmer # Gives profile info on
q1Programmer
What are the number of self seconds taken by:
FunctionSelf
secondsinitializeBigArray()__________countAdjacent()_______
___funkyFunction()__________(5 Points) Which optimizations
ought to be done by the compiler?
6. Which optimizations ought to be done by the
programmer?
Linker operation (55 Points total)
The program file p1.c below compiles under Linux to create
an object file p1.o.
It is to be linked with another file p2.o to create a running
program, whole.
/* p1.c
*/
#include <stdlib.h>
#include <stdio.h>
//
// Declarations go here:
//
// PURPOSE: To hold the length of the array pointed to by
'intArray'.
extern int length;
// PURPOSE: To hold the array of integers.
extern int* intArray;
// PURPOSE: To hold the maximum value that may place in
array 'intArray'.
extern int maxRandVal;
7. // PURPOSE: To:
// (1) have user enter 'length' (by calling 'enterValue()'),
// (2) have user enter 'maxRandVal' (by calling
'enterValue()'),
// (3) define 'intArray' (say 'intArray
=(int*)calloc(length,sizeof(int))')
// (4) fill 'intArray' with random numbers between 0-
'maxRandVal'
// (use expression '(rand() % (maxRandVal+1))')
// No parameters. No return value.
extern void createArray ();
// PURPOSE: To print the values in 'intArray[]'. No
parameters. No return
// value.
extern void printArray ();
//
// Function and variables go here:
//
// PURPOSE: To hold the minimum value for 'length'.
int minArrayLen = 1;
// PURPOSE: To hold the maximum value for 'length'.
int maxArrayLen = 256;
// PURPOSE: To hold the maximum value for 'maxRandVal'.
int maxMaxRandVal = 256;
// PURPOSE: To hold the length of C-string 'line'.
8. #define MAX_LINE 256
// PURPOSE: To hold the a C-string.
char line[MAX_LINE];
// PURPOSE: To have the user enter the variable pointed to by
'valuePtr',
// which must be between 'min' and 'max', and which is
described by
// '*descriptionPtr'. No parameters. No return value.
void enterValue (const char* descriptionPtr,
int min,
int max,
int* valuePtr
)
{
do
{
printf("Please enter the %s (%d-%d):
",descriptionPtr,min,max);
fgets(line,MAX_LINE,stdin);
*valuePtr = strtol(line,NULL,10);
}
while ( (*valuePtr < min) || (*valuePtr > max) );
}
// PURPOSE: To free 'intArray'. No parameters. No return
value.
//
void freeArray ()
{
9. free(intArray);
}
// PURPOSE: To define the array, print an array, and free the
array. No
// Ignores parameters. Returns 'EXIT_SUCCESS' to OS.
int main ()
{
createArray();
printArray();
freeArray();
return(EXIT_SUCCESS);
}
Sample output:[[email protected] Assign1]$ gcc -c p1.c
[[email protected] Assign1]$ gcc -c p2.c
[[email protected] Assign1]$ gcc -o whole p1.o p2.o
[[email protected] Assign1]$ ./whole
Please enter the array's length (1-256): 0
Please enter the array's length (1-256): 257
Please enter the array's length (1-256): 16
Please enter the maximum random value (1-256): 0
Please enter the maximum random value (1-256): 257
Please enter the maximum random value (1-256): 4
The array is:
intArray[0] = 3
intArray[1] = 1
intArray[2] = 2
intArray[3] = 0
intArray[4] = 3
intArray[5] = 0
intArray[6] = 1
intArray[7] = 2
intArray[8] = 4
intArray[9] = 1
intArray[10] = 2
10. intArray[11] = 2
intArray[12] = 0
intArray[13] = 4
intArray[14] = 3
intArray[15] = 1
[[email protected] Assign1]$
(30 Points) Write a program file p2.c that would compile to
p2.o, and would link with p1.o to create a legal running
program whole.
Important: Include your p2.c with your submission!
HINTS:
What does p1.c need that it does not define?Be sure to
extern any necessary functions with the same parameters as they
are declared.
What does p1.c define that p2.c would need?
Be sure to extern both such variable and function
symbols.
Create the individual object files and the complete
executable with:
linux> gcc -c p1.c # creates p1.o
linux> gcc -c p2.c # creates p2.o
linux> gcc p1.o p2.o -o whole # creates whole
linux> ./whole # runs whole
(5 Points) Use objdump (not gdb!) to disassemble both main()
and createArray() in whole.
Find the call to createArray() in main().
Show the math of how the number in that call instruction
is used to compute the address where createArray() actually is.
11. (5 Points) Which segment (that is: .text, .rodata, .data or
.bss) of p1.o has string constant
used in enterValue()'s printf() call?
Show this with objdump.
(5 Points) Can you find the memory for enterValue()'s
variable min using objdump?
If you can, use objdump to show where it is.
If you can't, tell why not.
(5 Points) Which segment of p2.o has the function
printArray()?
Show this with objdump.
(5 Points) It is rather inelegant for both p1.c and
p2.c to have the code:
// PURPOSE: To hold the length of C-string 'line'.
#define MAX_LINE 256
because if we decide to make a change we have to
remember to change all .c files.
Suggest a more elegant solution, one that C encourages.