Here - SEAS - George Washington University

advertisement
Department of Computer Science
School of Engineering and Applied Science
The George Washington University
CS-136: Computer Architecture II
Assignment 1 "The Need for Speed": MergeSort
Due Date: Midnight, Sunday, February 13, 2005
Objectives: Learn Assembly. Learn procedure calls. Practice converting "critical" code from a
high level language to assembly.
Structure:
You've just arrived at your summer internship at foo.com. You are working as part of
a team writing a program in a high-level language (C in this case...). You mention in
passing that you're pretty good at assembly language. Unfortunately the team's
program is REALLY slow. The team uses a program called a "profiler" to determine
what section of code is responsible slowing down the program. The team discovers
that the MergeSort function is really slow...
You have a brilliant idea..
"Hey, I've heard that you can speed your programs up by rewriting your slowest
functions in assembly!".
The team rewards your CSCI136 knowledge by putting you in charge of converting the
MergeSort function to MIPS assembly.
The MergeSort function sorts an array of integers in to increasing order. The function
works by dividing the array in to half and then calling itself with each half of the array.
When MergeSort is called with a 1 element array... it knows that the array is sorted...
so it simply returns. (This is known as the base case.) When the recursive calls
return in to the parent function... the parent function has two sorted halves of an array.
The function must combine these halves in to a single sorted array (called merging).
The merge is pretty intuitive.. we'll use a temporary array to help out. We'll start at the
beginning of each sorted half and use index variables to keep track of where we are in
each half. We'll compare the first integer in each of the halves.. and choose the
smaller value to go in to the temporary array. We'll then move the index variable
ahead in the half we chose the integer from... and do another comparison and copy to
the temp array.
Eventually we'll reach the end of one of the halves... we'll then have to copy what is
remaining of the other half in to the temporary array. After copying the remaining
elements, the temporary array is sorted. We'll finish by copying the temporary array
back to the original array.
Lets take a look at MergeSort:
The following slide is from http://www.eca.com.ve/cs/it_page/Sort_Algorithms/merge_sort.htm
I used COMPUTER ALGORITHMS by Horowitz, Sahni, et. al for algorithm information. Here is the
high level language implementation of MergeSort:
Note C array indexs start at 0.. like Java. This program will run in Java with very minor modifications.
//The arrays are "passed by reference" that is.. the address of the array is
//passed to the function as a parameter instead of the actual array itself
//The low and high values are "passed by value".. that is actual values are
//passed to function
//ourArray holds the array to be sorted
//tempArray is a blank array available to use to help in merge
//low holds the element number of lowest element in array
//high holds the element number of the highest element in array
void MergeSort(int ourArray[], int tempArray[], int low, int high) {
int middle;
int lowerIndex, upperIndex, newIndex;
int count;
//If there is only 1 element in the array... it is sorted
if (low==high) {
return;
}
middle=((high-low)/2)+low;
MergeSort(ourArray,tempArray,low,middle);
MergeSort(ourArray,tempArray,middle+1,high);
//Now we have 2 parts of our array sorted... we now need to combine them
lowerIndex=low;
newIndex=low;
upperIndex=middle+1;
//While we haven't reached the end of a half
while((lowerIndex<=middle)&&(upperIndex<=high)) {
//Choose the smallest element and put it in the tempArray
if (ourArray[lowerIndex]<=ourArray[upperIndex]) {
tempArray[newIndex]=ourArray[lowerIndex];
//Move to next element in lower half
lowerIndex=lowerIndex+1;
}
else {
tempArray[newIndex]=ourArray[upperIndex];
//Move to next element in upper half
upperIndex=upperIndex+1;
}
//Move to next element in the temp array
newIndex=newIndex+1;
}
if (lowerIndex>middle) {
//We finished with the lower half so we now have to finish copying the
//upper part of the array in to sorted array
for (count=upperIndex; count<=high; count++) {
tempArray[newIndex]=ourArray[count];
newIndex=newIndex+1;
}
}
if (upperIndex>high) {
//We finished with the upper half so now we have to finish copying the
//lower part of the array in to sorted array
for (count=lowerIndex; count<=middle; count++) {
tempArray[newIndex]=ourArray[count];
newIndex=newIndex+1;
}
}
//finally we need to copy the temp array back to the main array
for (count=low; count<=high; count++) {
ourArray[count]=tempArray[count];
}
}
int main () {
int ourArray[24]={54,23,56,32,99,7,4,2,88,9,11,21,
39,55,100,101,43,1,3,69,-5,-24,-17,0};
int tempArray[24];
MergeSort(ourArray,tempArray,0,23);
}
My assembly code was about ~170 lines.. about 75% of which were actual
instructions (the rest were comments). I provide this figure as a rough
benchmark... If you have more than ~300 lines... you probably should get help...
you're probably doing something wrong. For every C instruction... there should
be typically 2-3 MIPS instructions.. and at most 5.
The C and Assembly versions of this program together took me about 4 hours. I
estimate that the Assembly version will probably take you 6-12 hours. If you
don't understand something get help!
Hints:
1. Let's look at the starter code:
.text
.globl main
main:
la $a0,ourArray
la $a1,tempArray
li $a2,0
la $t0,arraySize
lw $a3,0($t0)
addi $a3,$a3,-1
jal MergeSort
#the first element in the array to sort is element 0
#we have to get the actual value in there
#the last element in the array to sort is size-1
done:
#We're finished- so syscall to exit
li $v0,10
syscall
.data
The main corresponds to the int main() in the C code (except we don't print).
Notice that we set up the function parameters for you. There are NO parameters
passed on the stack.
Here's the data segment:
.data
#Here's our array
ourArray: .word 54,23,56,32,99,7,4,2,88,9,11,21,39,55,100,101,43,1,3,69,-5,-24,-17,0
#since .space command requires #bytes, tempArray should be set to 4x the arraySize
tempArray: .space 96
arraySize: .word 24
Look at how the parameters are being passed to your function:
#MergeSort Function
#Parameters:
#$a0 holds the address of ourArray (the array of integers were going to sort)
#$a1 hodls the address of tempArray (a temporary array that we can use to copy in to)
#$a2 holds the value of low, which is the lowest element number of the array
#$a3 holds the value of high, which is the highest element number of the array
ourArray and tempArray are already set up for you in the data segment
2. You'll have to save some information on the stack before making the recursive
function calls.
3. Choose your registers for your variables intelligently. You have plenty of registers...
You should have register assignments figured out beforehand so you know how to
adjust stack pointer and what you need to save.
Required
MergeSort function. A main has been provided.
Functions:
Output:
You should be able to look at the SPIM data segment (3rd window down) and see that
the array has been sorted:
DATA
[0x10000000]...[0x1000fffc]
[0x1000fffc]
[0x10010000]
[0x10010010]
[0x10010020]
[0x10010030]
[0x10010040]
[0x10010050]
0x00000000
0x00000000
0xffffffe8 0xffffffef
0x00000001 0x00000002
0x00000007 0x00000009
0x00000017 0x00000020
0x00000036 0x00000037
0x00000058 0x00000063
0xfffffffb
0x00000003
0x0000000b
0x00000027
0x00000038
0x00000064
0x00000000
0x00000004
0x00000015
0x0000002b
0x00000045
0x00000065
Please note that these numbers are in HEX. (-24, -17, -5, 0, 1, 2, ...)
With the following data segment here are the relevant results:
.data
#Here's our array
ourArray: .word 354,223,156,31,99,-7,0,2,-88,9,333111,54321,39,-55,101,105,43,-1,3
#since .space command requires #bytes tempArray should be set to 4x arraySize
tempArray: .space 76
arraySize: .word 19
DATA
[0x10000000]...[0x1000fffc]
[0x1000fffc]
[0x10010000]
[0x10010010]
[0x10010020]
[0x10010030]
[0x10010040]
0x00000000
0x00000000
0xffffffa8 0xffffffc9
0x00000000 0x00000002
0x0000001f 0x00000027
0x00000065 0x00000069
0x00000162 0x0000d431
0xfffffff9
0x00000003
0x0000002b
0x0000009c
0x00051537
0xffffffff
0x00000009
0x00000063
0x000000df
Can I work on other computers?
Frequently Sure. We will grade using PCSpim, but there shouldn't be any problems...
Asked
Questions: I don't understand MergeSort. What can I do?
Feel free to look on the WWW for explanations, Java, Ada and C exmaple code. Do
NOT look at MIPS assembly code.
Do and
Do Not:
Do:
comment your code- recommend comments on same line out to the side instructions... helpful in SPIM
use pseudo instructions (but PLEASE try to understand what is happening.. this will help you later!)
use debugging features of SPIM
Do Not:
look at MergeSort assembly code from the WWW
Some helpful functions:
sll, srl, bgt, ble
What to
Turn in:
Directions:
1. Download the merge.s file off the web. (If desired you can download merge.c file also).
2. Send an email with your final commented merge.s as an attachment to:
jinfc@gwu.edu
fliu@gwu.edu
cheng@gwu.edu
Academic
Integrity:
Remember the policy on academic integrity: You may discuss the assignment with others, but
you are to do your own work. The official University statement for Academic Integrity, and the
Department of Computer Science's policy on Academic Integrity can be accessed HERE.
Download