Page 1 of 2

[NXC] Optimize this code?

Posted: 27 Jan 2012, 01:17
by nxtboyiii
Hi,
If you download muntoo's SCR_FILE_LIB and run this program you will notice how slow the particles move.
**BTW, I did not make the algorithm for this water simulation.
I want the water particles to move faster but still smooth, but I do not know how to do it other than decreasing the # of water particles.
Here's the code:

Code: Select all

#include "SCR_File_lib.nxc"

#define NUM_OF_PARTICLES 100

task main()
{
 byte map[100][64];
 int px[NUM_OF_PARTICLES];
 int py[NUM_OF_PARTICLES];
 bool pactive[NUM_OF_PARTICLES];
 int tpx,tpy;
 	byte ScreenMem[];
	ArrayInit(ScreenMem, 0x00, 800);
 ScreenMem[799] = 0x0F;
 for(int c=0; c < NUM_OF_PARTICLES; c++)
 {
  pactive[c]=1;
 }
 for(int c=0; c < 24; c++)
 {
  px[c]=40;
  py[c]=c+40;
 }
  for(int c=24; c < 40; c++)
 {
  px[c]=41;
  py[c]=c+40-24;
 }
   for(int c=40; c < NUM_OF_PARTICLES; c++)
 {
  px[c]=42;
  py[c]=c;
 }
    for(int c=60; c < NUM_OF_PARTICLES; c++)
 {
  px[c]=39;
  py[c]=c-20;
 }
     for(int c=80; c < NUM_OF_PARTICLES; c++)
 {
  px[c]=38;
  py[c]=c-40;
 }

 for(int c=0; c < 100; c++)
 {
  map[c][30]=1;
 }
  for(int c=0; c < 100; c++)
 {
  map[c][0]=1;
 }
  for(int c=0; c < 64; c++)
 {
  map[99][c]=1;
 }
 for(int c=0; c < 64; c++)
 {
  map[0][c]=1;
 }
 for(int c=0; c < 20; c++)
 {
  map[Random(98)+1][30]=0;
 }
  int x,y;
  x=30;
  y=20;
 repeat(20)
 {
  x++;
  y++;
  map[x][y]=1;
 }
   x=20;
  y=40;
 repeat(20)
 {
  x++;
  y--;
  map[x][y]=1;
 }
 	unsigned long dispAddr;                  //Draws the map and saves it to ScreenMem
 	dispAddr = DisplayDisplay();
	SetDisplayDisplay(addressOf(ScreenMem));
  for(int c=0; c < 100; c++)
  {
   for(int d=0; d < 64; d++)
   {
    if(map[c][d] == 1)
    {
     PointOut(c,d);
    }
   }
  }
	SetDisplayDisplay(dispAddr);
	DisplayScreenMem(ScreenMem);
 while(1)
 {
  SetDisplayFlags( DISPLAY_REFRESH_DISABLED );
  ClearScreen();
    DisplayScreenMem(ScreenMem);
  for(int c=0; c < NUM_OF_PARTICLES; c++)
  {
   if(pactive[c])
   {
   tpx=px[c];
   tpy=py[c];
   map[tpx][tpy]=0;
   if(map[tpx][tpy-1] == 0)
   {
    tpy--;
   }
   else if(map[tpx+1][tpy] == 0)
   {
    if(map[tpx-1][tpy] == 0)
    {
     tpx+=Random(3)-1;
    }
    else
    tpx++;
   }
   else     if(map[tpx-1][tpy] == 0)
    {
     tpx--;
    }
   PointOut(tpx,tpy);
   map[tpx][tpy]=1;
   px[c]=tpx;
   py[c]=tpy;
   }
  }
  SetDisplayFlags( DISPLAY_ON | DISPLAY_REFRESH );
  Wait(17);
 }
}
Thanks, and have a nice day,
nxtboy III

Re: [NXC] Optimize this code?

Posted: 30 Jan 2012, 18:19
by mcsummation
Before I bother to download your code and munge through it, what OPT level are you running in the compiler?

Re: [NXC] Optimize this code?

Posted: 01 Feb 2012, 01:58
by nxtboyiii
Optimization level 2.

Re: [NXC] Optimize this code?

Posted: 01 Feb 2012, 14:44
by mcsummation
Just how fast do you want it to run? I compiled it with the latest compiler and run it on the latest firmware and it runs about as fast as I can comfortably watch the fluid spill into the cone.

It will take me some time to analyze the code and determine what part needs to be worked on.

Re: [NXC] Optimize this code?

Posted: 01 Feb 2012, 15:30
by nxtboyiii
Well I want to be able to have, like 150-200 particles while still running at about as fast as the original program runs 100 particles.

Re: [NXC] Optimize this code?

Posted: 01 Feb 2012, 15:34
by mcsummation
Oh, OK. Now I understand. Will get back after looking at code.

Re: [NXC] Optimize this code?

Posted: 01 Feb 2012, 17:19
by spillerrec
I gave it a go too, try it out:

Code: Select all

#include "SCR_File_lib.nxc"

#define NUM_OF_PARTICLES 100

#define WIDTH	(100)
#define HEIGHT	(64)

#define xy( x, y ) ( (y)*WIDTH + (x) )

task main(){
	byte map[ WIDTH * HEIGHT ];
	int p[NUM_OF_PARTICLES];
	byte ScreenMem[];
	ArrayInit(ScreenMem, 0x00, 800);
	ScreenMem[799] = 0x0F;
	
	for(int c=0; c < 24; c++)
		p[c] = xy( 40, c+40 );
	for(int c=24; c < 40; c++)
		p[c] = xy( 41, c+40-24 );
	for(int c=40; c < NUM_OF_PARTICLES; c++)
		p[c] = xy( 42, c );
	for(int c=60; c < NUM_OF_PARTICLES; c++)
		p[c] = xy( 39, c-20 );
	for(int c=80; c < NUM_OF_PARTICLES; c++)
		p[c] = xy( 38, c-40 );

	for(int c=0; c < 100; c++)
		map[ xy( c, 30 ) ] =1;
	for(int c=0; c < 100; c++)
		map[ xy( c, 0 ) ]=1;
	for(int c=0; c < 64; c++)
		map[ xy( 99, c ) ]=1;
	for(int c=0; c < 64; c++)
		map[ xy( 0,c ) ]=1;
	for(int c=0; c < 20; c++)
		map[ xy( Random(98)+1, 30 ) ]=0;
	
	int x,y;
	x=30;
	y=20;
	repeat(20){
		x++;
		y++;
		map[ xy( x, y ) ]=1;
	}
	x=20;
	y=40;
	repeat(20){
		x++;
		y--;
		map[ xy( x, y ) ]=1;
	}
	
	unsigned long dispAddr;                  //Draws the map and saves it to ScreenMem
	dispAddr = DisplayDisplay();
	SetDisplayDisplay(addressOf(ScreenMem));
	for(int c=0; c < 100; c++){
		for(int d=0; d < 64; d++){
			if(map[ xy( c, d ) ] == 1)
				PointOut(c,d);
		}
	}
	SetDisplayDisplay(dispAddr);
	DisplayScreenMem(ScreenMem);
	
	while(1){
		SetDisplayFlags( DISPLAY_ON | DISPLAY_REFRESH );
		
		for(int c=0; c < NUM_OF_PARTICLES; c++){
			int tp = p[c], org = tp;
			
			if(map[ tp - WIDTH ] == 0)
				tp -= WIDTH;
			else if(map[ tp + 1 ] == 0){
				if(map[ tp - 1 ] == 0)
					tp += Random(3)-1;
				else
					tp++;
			}
			else if(map[ tp - 1] == 0)
				tp--;
			else
				continue;
			
			map[org] = 0;
			map[tp]=1;
			p[c]=tp;
		}
		
		SetDisplayFlags( DISPLAY_REFRESH_DISABLED );
		DisplayScreenMem(ScreenMem);
		
		int c = NUM_OF_PARTICLES;
		do{
			int tp = p[--c];
			PointOut(tp%WIDTH,tp/WIDTH);
		}while( c > 0 );
	}
}
The repeated calls to PointOut is costly though, it makes up roughly half of the time for each iteration... : \

EDIT: btw, I threw out the pactive array since it was unused here...
EDIT2: I used optimization level 3 here btw

Re: [NXC] Optimize this code?

Posted: 01 Feb 2012, 18:00
by nxtboyiii
Wow, thanks a ton, spillerec!
I haven't tested it out yet but it looks like this could make it speed up a lot. :)
Thank you so much.

Have a nice day,
nxtboyIII

Re: [NXC] Optimize this code?

Posted: 01 Feb 2012, 18:21
by mattallen37
Here is a slightly modified version of spillerrec's program

Code: Select all

   while(1){
      SetDisplayFlags( DISPLAY_ON | DISPLAY_REFRESH );

      for(int c=(NUM_OF_PARTICLES-1); c+1; c--){
         int tp = p[c], org = tp;

         if(map[ tp - WIDTH ] == 0)
            tp -= WIDTH;
         else if(map[ tp + 1 ] == 0){
            if(map[ tp - 1 ] == 0)
               tp += Random(3)-1;
            else
               tp++;
         }
         else if(map[ tp - 1] == 0)
            tp--;
         else
            continue;

         map[org] = 0;
         map[tp]=1;
         p[c]=tp;
      }

      SetDisplayFlags( DISPLAY_REFRESH_DISABLED );
      DisplayScreenMem(ScreenMem);
      asm {set __PointOutArgs.Options, 0}
      
      int c = NUM_OF_PARTICLES;
      do{
         int tp = p[--c];
         asm{
            mod __signed_stack_001main, __main_7qG2_tp_7qG2_002, 100
            div __D0main, __main_7qG2_tp_7qG2_002, 100
            mov __PointOutArgs.Location.X, __signed_stack_001main
            mov __PointOutArgs.Location.Y, __D0main
            syscall 14, __PointOutArgs
         }
      }while(c);
   }
I don't know if it's noticeably faster, but it is less op codes.

Re: [NXC] Optimize this code?

Posted: 01 Feb 2012, 19:56
by nxtboyiii
Thanks a lot for the help! Your's and spillerec's help me a lot.
Once I test it out it should be a whole lot faster. :)