BookmarkSubscribeRSS Feed
☑ This topic is solved. Need further help from the community? Please sign in and ask a new question.
hellohere
Pyrite | Level 9

%global stind endind;
%let stind=0; %let endind=500; 
%macro m_sinx(nx, baseratio, noiseratio);
	/*%let nx=30;*/
	data temp_simu_sin_od;
	%do i=1 %to &nx;
		ybase=(round(ranuni(&i.),0.1)+0.1)*&baseratio.;
		%do x=&stind. %to &endind.;
			tick=&i.;
			ynoise=(ranuni(&i.)-0.5)*&noiseratio.*2*ranuni(&x.);
			y=ybase*sin(&x./200)+(ranuni(&i.)-0.5)*&noiseratio.*2*ranuni(&x.);	
			ind=&x.;
			output;
		%end;
	%end;
	run;quit;

%mend;

%m_sinx(300,20,0.5);

When nx=30, it takes only seconds. But when nx=300,  it takes forever. I have to stop in middle.

Any wrong with the coding?!

21830
21831  %m_sinx(30,20,0.5);

NOTE: The data set WORK.TEMP_SIMU_SIN_OD has 15030 observations and 5 variables.
NOTE: DATA statement used (Total process time):
      real time           3.52 seconds
      cpu time            3.56 seconds


21832 21833 %m_sinx(300,20,0.5); NOTE: DATA statement used (Total process time): real time 4:48.31 cpu time 4:03.35

 

1 ACCEPTED SOLUTION

Accepted Solutions
andreas_lds
Jade | Level 19

Start by removing the quit statement. 

Would replace the macro loops with normal loops:

%macro m_sinx(nx, baseratio, noiseratio);
	data temp_simu_sin_od;
    	do i = 1 to &nx.;
    		ybase = (round(ranuni(i) ,0.1) + 0.1) * &baseratio.;
    		do x = &stind. to &endind.;
    			tick = i;
    			ynoise = (ranuni(i) - 0.5) * &noiseratio. * 2 * ranuni(x);
    			y = ybase * sin(x / 200) + (ranuni(i) - 0.5) * &noiseratio. * 2 * ranuni(x);
    			ind = x;
    			output;
    		end;
    	end;

        drop i x;
	run;
%mend;

Log:

50         %m_sinx(300, 20, 0.5);

NOTE: The data set WORK.TEMP_SIMU_SIN_OD has 150300 observations and 5 variables.
NOTE:  Verwendet wurde: DATA statement - (Gesamtverarbeitungszeit):
      real time           0.03 seconds
      cpu time            0.03 seconds

View solution in original post

5 REPLIES 5
andreas_lds
Jade | Level 19

Start by removing the quit statement. 

Would replace the macro loops with normal loops:

%macro m_sinx(nx, baseratio, noiseratio);
	data temp_simu_sin_od;
    	do i = 1 to &nx.;
    		ybase = (round(ranuni(i) ,0.1) + 0.1) * &baseratio.;
    		do x = &stind. to &endind.;
    			tick = i;
    			ynoise = (ranuni(i) - 0.5) * &noiseratio. * 2 * ranuni(x);
    			y = ybase * sin(x / 200) + (ranuni(i) - 0.5) * &noiseratio. * 2 * ranuni(x);
    			ind = x;
    			output;
    		end;
    	end;

        drop i x;
	run;
%mend;

Log:

50         %m_sinx(300, 20, 0.5);

NOTE: The data set WORK.TEMP_SIMU_SIN_OD has 150300 observations and 5 variables.
NOTE:  Verwendet wurde: DATA statement - (Gesamtverarbeitungszeit):
      real time           0.03 seconds
      cpu time            0.03 seconds
FreelanceReinh
Jade | Level 19

Hello @hellohere,

 

The main issue with your code -- that it creates thousands of lines of code, while it should just create data -- is resolved by @andreas_lds's suggestion.

 

Also note that changing the seed of the RANUNI function within a DATA step is pointless: You get exactly the same result if you replace all those seed values by the first, which is 1 in your case. There are good reasons to switch from the deprecated RANUNI function to the RAND function (here: with the 'UNIFORM' distribution) anyway: see Six reasons you should stop using the RANUNI function to generate random numbers. (Then you would set the seed with the CALL STREAMINIT routine.)

 

To streamline the code further, you could replace variable x by variable ind and variable i by tick. Then you could delete the two assignment statements (for tick and ind) and the DROP statement.

hellohere
Pyrite | Level 9

Is this due to usage of %do instead of do inside macro?!

FreelanceReinh
Jade | Level 19

@hellohere wrote:

Is this due to usage of %do instead of do inside macro?!


Yes, the macro %DO loops unnecessarily generated tons of DATA step code, whereas the DO loops together with the OUTPUT statement in the inner loop efficiently create the data, as intended.

Tom
Super User Tom
Super User

@hellohere wrote:

Is this due to usage of %do instead of do inside macro?!


Become your own macro interpreter and see for yourself.

With the %DO loops the macro is generating code like:

data temp_simu_sin_od;
ybase=(round(ranuni(&i.),0.1)+0.1)*&baseratio.;
  tick=&i.;
  ynoise=(ranuni(&i.)-0.5)*&noiseratio.*2*ranuni(&x.);
  y=ybase*sin(&x./200)+(ranuni(&i.)-0.5)*&noiseratio.*2*ranuni(&x.);	
  ind=&x.;
  output;
  ynoise=(ranuni(&i.)-0.5)*&noiseratio.*2*ranuni(&x.);
  y=ybase*sin(&x./200)+(ranuni(&i.)-0.5)*&noiseratio.*2*ranuni(&x.);	
  ind=&x.;
  output;
  ynoise=(ranuni(&i.)-0.5)*&noiseratio.*2*ranuni(&x.);
  y=ybase*sin(&x./200)+(ranuni(&i.)-0.5)*&noiseratio.*2*ranuni(&x.);	
  ind=&x.;
  output;
...
ybase=(round(ranuni(&i.),0.1)+0.1)*&baseratio.;
  tick=&i.;
  ynoise=(ranuni(&i.)-0.5)*&noiseratio.*2*ranuni(&x.);
  y=ybase*sin(&x./200)+(ranuni(&i.)-0.5)*&noiseratio.*2*ranuni(&x.);	
  ind=&x.;
  output;
  ynoise=(ranuni(&i.)-0.5)*&noiseratio.*2*ranuni(&x.);
  y=ybase*sin(&x./200)+(ranuni(&i.)-0.5)*&noiseratio.*2*ranuni(&x.);	
  ind=&x.;
  output;
  ynoise=(ranuni(&i.)-0.5)*&noiseratio.*2*ranuni(&x.);
  y=ybase*sin(&x./200)+(ranuni(&i.)-0.5)*&noiseratio.*2*ranuni(&x.);	
  ind=&x.;
  output;
...

run;

So the data step will take a very long time to compile before it can even begin to generate the data.

 

It is always best to know what code you want the macro to emit before you start writing the macro.

sas-innovate-wordmark-gradient-background 3.pngSAS Innovate

Call for content now open!

It's your turn to help shape SAS Innovate 2027. Share your expertise and inspire the SAS community.

Submit your proposal →

How to Concatenate Values

Learn how use the CAT functions in SAS to join values from multiple variables into a single value.

Find more tutorials on the SAS Users YouTube channel.

SAS Training: Just a Click Away

 Ready to level-up your skills? Choose your own adventure.

Browse our catalog!

Discussion stats
  • 5 replies
  • 160 views
  • 2 likes
  • 4 in conversation