Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations strongm on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Code taking too long to execute

Status
Not open for further replies.

hummus

Programmer
Jul 2, 2008
15
US

Hi all, I wrote this code with random numbers that is taking too long to produce its output (probably due to the high number of random numbers being used). Any help to streamline the code would be appreciated. Thank you.

Code:
	PROGRAM Monte Carlo
	IMPLICIT NONE

	INTEGER :: i, nrandoms, iseed, seed, a, b
	INTEGER :: biny(39) !** change according to # of bins
	PARAMETER (iseed = 20000) !** change seed # to change pseudo-random sequence
	PARAMETER (seed = 10000)  !** change seed # to change pseudo-random sequence
	REAL :: En, rand, Neutrons

	DIMENSION En(5000000) !** change according to # of randoms
	DIMENSION Neutrons(5000000) !** change according to # of randoms

	CALL SRAND(iseed)

	
	DO i=1, 39 !** change according to # of bins/ set bins initially to 0

		biny(i) = 0

	END DO


	WRITE(*,*) 'Enter the number of randoms'

	READ(*,*) nrandoms

	
	DO a=1, nrandoms
	
	  Neutrons(a) = rand()

		IF (Neutrons(a) > .0284 .AND. Neutrons(a) <= .0411) THEN
		
		CALL SRAND(seed)

		DO b=1, nrandoms
	
	    	En(b) = rand()

			IF (En(b) > .01533 .AND. En(b) <= .002752) THEN

			biny(1) = biny(1) + 1
			ELSEIF (En(b) <= .04142) THEN
	
			biny(2) = biny(2) + 1
			ELSEIF (En(b) <= .05660) THEN
	
			biny(3) = biny(3) + 1
			ELSEIF (En(b) <= .07274) THEN
	
			biny(4) = biny(4) + 1
			ELSEIF (En(b) <= .08964) THEN
	
			biny(5) = biny(5) + 1
			ELSEIF (En(b) <= .10710) THEN
	
			biny(6) = biny(6) + 1
			ELSEIF (En(b) <= .12499) THEN
	
			biny(7) = biny(7) + 1
			ELSEIF (En(b) <= .14319) THEN
	
			biny(8) = biny(8) + 1
			ELSEIF (En(b) <= .16160) THEN
	
			biny(9) = biny(9) + 1
			ELSEIF (En(b) <= .18014) THEN
	
			biny(10) = biny(10) + 1
			ELSEIF (En(b) <= .19875) THEN
	
			biny(11) = biny(11) + 1
			ELSEIF (En(b) <= .21735) THEN
	
			biny(12) = biny(12) + 1
			ELSEIF (En(b) <= .23591) THEN
	
			biny(13) = biny(13) + 1
			ELSEIF (En(b) <= .25437) THEN
	
			biny(14) = biny(14) + 1
			ELSEIF (En(b) <= .27269) THEN
	
			biny(15) = biny(15) + 1
			ELSEIF (En(b) <= .29085) THEN
	
			biny(16) = biny(16) + 1
			ELSEIF (En(b) <= .30882) THEN
	
			biny(17) = biny(17) + 1
			ELSEIF (En(b) <= .32658) THEN
	
			biny(18) = biny(18) + 1
			ELSEIF (En(b) <= .48895) THEN
	
			biny(19) = biny(19) + 1
			ELSEIF (En(b) <= .62008) THEN
	
			biny(20) = biny(20) + 1
			ELSEIF (En(b) <= .72144) THEN
	
			biny(21) = biny(21) + 1
			ELSEIF (En(b) <= .79777) THEN
	
			biny(22) = biny(22) + 1
			ELSEIF (En(b) <= .85429) THEN
	
			biny(23) = biny(23) + 1
			ELSEIF (En(b) <= .89564) THEN
	
			biny(24) = biny(24) + 1
			ELSEIF (En(b) <= .92561) THEN
	
			biny(25) = biny(25) + 1
			ELSEIF (En(b) <= .94718) THEN
	
			biny(26) = biny(26) + 1
			ELSEIF (En(b) <= .96262) THEN
	
			biny(27) = biny(27) + 1
			ELSEIF (En(b) <= .97362) THEN
	
			biny(28) = biny(28) + 1
			ELSEIF (En(b) <= .98143) THEN
	
			biny(29) = biny(29) + 1
			ELSEIF (En(b) <= .98696) THEN
	
			biny(30) = biny(30) + 1
			ELSEIF (En(b) <= .99086) THEN
	
			biny(31) = biny(31) + 1
			ELSEIF (En(b) <= .99360) THEN
	
			biny(32) = biny(32) + 1
			ELSEIF (En(b) <= .99688) THEN
	
			biny(33) = biny(33) + 1
			ELSEIF (En(b) <= .99848) THEN
	
			biny(34) = biny(34) + 1
			ELSEIF (En(b) <= .99927) THEN
	
			biny(35) = biny(35) + 1
			ELSEIF (En(b) <= .99965) THEN
	
			biny(36) = biny(36) + 1
			ELSEIF (En(b) <= .99983) THEN
	
			biny(37) = biny(37) + 1
			ELSEIF (En(b) <= .99992) THEN
	
			biny(38) = biny(38) + 1
			ELSEIF (En(b) <= .99996) THEN
	
			biny(39) = biny(39) + 1

			END IF

		END DO

		END IF

	  END DO

	WRITE(*,*) (biny(i), i=1, 39) !** change according to # of bins

	END PROGRAM Monte Carlo
[code]
 
Instead of creating 5000000 more randoms numbers each time for the (En(b)), I just need to create one random number each time a random number falls into the (Neutrons(a) > .0284 .AND. Neutrons(a) <= .0411) range.
 

I modified the code, and it seems to work, but I would like to make sure I am doing this right:

Code:
	PROGRAM Test
	IMPLICIT NONE

	INTEGER :: i, nrandoms, iseed, seed, a
	INTEGER :: biny(39) !** change according to # of bins
	PARAMETER (iseed = 20000) !** change seed # to change pseudo-random sequence
	REAL :: En, rand, Neutrons

	DIMENSION Neutrons(5000000) !** change according to # of randoms

	CALL SRAND(iseed)

	
	DO i=1, 39 !** change according to # of bins/ set bins initially to 0

		biny(i) = 0

	END DO


	WRITE(*,*) 'Enter the number of randoms'

	READ(*,*) nrandoms

	
	DO a=1, nrandoms
	
	  Neutrons(a) = rand()

		IF (Neutrons(a) > .0284 .AND. Neutrons(a) <= .0411) THEN
		
	    	En = rand()

			IF (En > .01533 .AND. En <= .02752) THEN

			biny(1) = biny(1) + 1
			ELSEIF (En <= .04142) THEN
	
			biny(2) = biny(2) + 1
			ELSEIF (En <= .05660) THEN
	
			biny(3) = biny(3) + 1
C Repeat up to biny(39)

END IF

		END IF

	  END DO

	WRITE(*,*) (biny(i), i=1, 39) !** change according to # of bins

	END PROGRAM Test

Thanks!

 
The most interesting counter-question: what do you want to achieve with this strange (the 1st version especially) and ineffective code?
 
Do you need to store an array of neutrons?
Code:
    PROGRAM Test
    IMPLICIT NONE

    INTEGER :: i, nrandoms, iseed, seed, a
    INTEGER :: biny(39) !** change according to # of bins
    PARAMETER (iseed = 20000) !** change seed # to change pseudo-random sequence
    REAL :: En, rand, Neutrons

    CALL SRAND(iseed)

    ! You can use the array feature
    biny = 0


    WRITE(*,*) 'Enter the number of randoms'

    READ(*,*) nrandoms

    
    DO a=1, nrandoms
    
      Neutrons = rand()

        IF (Neutrons > .0284 .AND. Neutrons <= .0411) THEN
        
            En = rand()

            IF (En > .01533 .AND. En <= .02752) THEN

            biny(1) = biny(1) + 1
            ELSEIF (En <= .04142) THEN
    
            biny(2) = biny(2) + 1
            ELSEIF (En <= .05660) THEN
    
            biny(3) = biny(3) + 1
C Repeat up to biny(39)

            END IF

        END IF

      END DO

    WRITE(*,*) (biny(i), i=1, 39) !** change according to # of bins

    END PROGRAM Test
 
Actually, biny(1) will be rather full. I think the logic should read
Code:
if (en >= 0.02752 .and. en < 0.01533) then
   biny(1) = biny(1) + 1
elseif ...
[code]
Alternatively
[code]
integer, parameter:: RANGEMAX = 39
real range(RANGEMAX)
data range /0.01533, 0.4142 ... /
...
        IF (Neutrons > .0284 .AND. Neutrons <= .0411) THEN
        
            En = rand()

            if (en .gt. 0.02752) then
            do i = 1, RANGEMAX, 1
               if (en < range(i) then
                  biny(i) = biny(i) + 1
                  exit do
               end if
            end do
            end if
        endif
...
May take slightly longer to run but a lot less code
 
Your original program took 7.7 secs for 100,000 and 10.7 mins for 1,000,000.

 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top