CSC231 Homework 10 2010

From dftwiki3
Revision as of 19:27, 7 December 2010 by Thiebaut (talk | contribs) (Finding primes less than 2,000,000)
Jump to: navigation, search

--D. Thiebaut 23:57, 7 December 2010 (UTC)


This assignment is due on the last day of class, Tuesday 12/14 evening, at midnight.



Page under construction!
UnderConstruction.jpg

Your assignmnent

  • Using compiler optimization techniques, modify the program below and make it run faster.

Finding primes less than 2,000,000

  • The assembly program below tests all the integers between 2 and 2,000,000 (not included) and counts the number of primes found.

; findPrime.asm
; D. Thiebaut
;
; this program counts the number of primes number less than 1,000,000.
;
; to assemble and run:
;
; nasm  -f elf -F stabs asm_io.asm
; nasm  -f elf -F stabs findPrime.asm
; gcc -c driver.c
; gcc  asm_io.o findPrime.o driver.o  -o findPrime
;
; C++ version of the program
; --------------------------
;#include<iostream>
;
;using namespace std;
;
;bool isPrime( int n );
;
;int main(){
;  int N = 2000000;
;  int count = 0;
;
;  for ( int n = 2; n < N; n++ ) 
;    if ( isPrime( n ) )
;      //cout << n << endl;
;      count++;
;
;  cout << count << endl;
;  return 0;
;}
;
;bool isPrime( int n ) {
;  for ( int i=2; i*i <= n ; i++ )
;    if ( n % i == 0 )
;      return 0;
;  
;  return 1;
;}
;
%include "asm_io.inc"


	 section	.data
N	 dd	0 		; typically set to 1,000,000
count	 dd	0		; number of primes found
n	 dd	0		; variable tested for prime property
i	 dd	0		; index of for loop

	 section	.text
	 global		asm_main

asm_main:
	mov	dword[N], 2000000 ; initialize N
	mov	dword[count], 0	  ; initialize count

;  for ( int n = 2; n < N; n++ ) 
;    if ( isPrime( n ) )
;      //cout << n << endl;
;      count++;	

       mov	dword[n], 2
forn:  mov	eax, dword[n]
       cmp	eax, dword[N]
       jge	endForn

if:    push	ax		; make room for returned value
       push	dword[n]
       call	isPrime
       pop	ax		; get returned boolean
       cmp	ax, 1
       jne	endif
       inc	dword[ count ]
endif:

       inc	dword[ n ]
       jmp	forn

endForn:
       mov	eax, [count]	; print count
       call	print_int
       call	print_nl	

       ret

;-----------------------------------------------------------------
; isPrime function.
; gets n in stack.  Returns true/false through the stack
;
;bool isPrime( int n ) {
;  for ( int i=2; i*i <= n ; i++ )
;    if ( n % i == 0 )
;      return 0;
;
;  return 1;
;}
;-----------------------------------------------------------------
isPrime:
      push	ebp
      mov	ebp, esp
      sub	esp, 4			; make room in stack for i

%define ip_ret 	word[ebp+12]
%define ip_n	dword[ebp+8]
%define ip_i	dword[ebp-4]

       mov	ip_i, 2
.for:  mov	eax, ip_i		; compare n to i*i
       mov	ebx, ip_i
       mul	ebx
       cmp	eax, ip_n
       ja	.endFor

.if:   mov	edx, 0			; divide n by i
       mov	eax, ip_n
       mov	ebx, ip_i
       div	ebx
       cmp	edx, 0			; test modulo (remainder)
       jne	.end_if
       
.ret0:
      mov	ip_ret, 0		; return 0
      mov	esp, ebp
      pop	ebp
      ret	4

.end_if:
      inc	ip_i
      jmp	.for

.endFor:
      mov	ip_ret, 1		; return 1
      mov	esp, ebp
      pop	ebp
      ret	4


  • When run on grendel at 7:00 p.m., here are the execution times observed:
bash
for i in 1 2 3 4 ; do time findPrime; echo ; done

148933

real	0m4.220s
user	0m4.207s
sys	0m0.001s

148933

real	0m4.236s
user	0m4.208s
sys	0m0.002s

148933

real	0m4.272s
user	0m4.246s
sys	0m0.003s

148933

real	0m4.267s
user	0m4.207s
sys	0m0.003s
So, the program takes about 4.24 seconds of user time to find all the primes less than 2,000,000.
  • Your assignment is to modify the assembly language program using some of the compiler optimization techniques we covered in class, and lower its user execution time.

Comparison

  • The C program used as documentation in the assembly program above is shown below:
// findPrime.cpp
// D. Thiebaut
// computes the number of prime integers less than 2,000,000
// and prints out this number
//
// To compile and run:
// g++ -o findPrime2 findPrime.cpp
// ./findPrime2
//
// To compile and use as much optimization as the compiler can generate:
// g++ -O3 -o findPrim3 findPrime.cpp
// ./findPrime3
//

#include<iostream>

using namespace std;

//------------------------------------------------------
// prototypes
bool isPrime( int n );

//------------------------------------------------------
int main(){
  int N = 2000000;
  int count = 0;

  //--- test all integers less than 2,000,000 ---
  for ( int n = 2; n < N; n++ ) 
    if ( isPrime( n ) )
      //cout << n << endl;
      count++;

  cout << count << endl;
  return 0;
}

//------------------------------------------------------
// isPrime( int n )
// return true (1) if n is prime, 0 otherwise
//------------------------------------------------------
bool isPrime( int n ) {
  for ( int i=2; i*i <= n ; i++ )
    if ( n % i == 0 )
      return 0;
  
  return 1;
}