In general when I press the Break button to interrupt a CPU intensive IML program, I find that it is extremely unresponsive. If I am patient it will run for many minutes before it releases control back to me, so instead I resort to killing SAS in the Windows Task Manager, but only provided I have remembered to save what I was doing!
I have fudged a way around this. In my main program loop, I am considering using syntax like:
do i = 1 to 1E10;
if mod(i, 1E5) = 0 then do;
< do stuff here >
In my tests, this does make IML much more responsive to pressing the break button. But you either have to put up with the flood of notes to the log window, or kill notes for the whole program. Is there a better way? A system option perhaps? A different way of structuring my IML program? I am using 9.4 in Windows 7.
That's an interesting problem (and solution). When your program is deep inside a compuational routine (say, an eigenvector computation), it can't check for an interrupt. So the more efficient your code is, the worse this problem will be.
I think you can use the EXECUTE statement to implement the flavor or your solution without experiencing the NOTES/Log problem. I don't think the statement that you execute is important, but try this:
if mod(i, 1E5) = 0 then do;
Thanks Rick, the call execute trick does work for me.
I suspect IML on my machine is checking for interrupts less frequently than you imagine. If I run :
do i = 1 to 2E8;
j = i;
then it takes a little less than 30 secs CPU to complete without interruption. However if I press the break button 2 seconds into the run, it appears to ignore it until the loop has completed, since the log always reports about the same CPU time after "user asked for termination".
Oh, I realize that IML doesn't check for interrupts very frequently. By design, IML is optimized to execute quickly. It compiles the entire DO loop and then executes it as a unit. That is why a DO loop in IML is not as expensive as in some other matrix-vector languages.
You might also try CALL EXECUTE(";"), which would have no side effects. [Untested idea.]
Another thought: You could write a macro that would replace the single loop with multiple loops. For example,
%SplitLoops(i=1 to 1E8, 10, <code>);
could resolve to 10 DO loops that each execute <code>. The first loop is i=1 to 1e7, the next is i=1e7+1 to 2e7, and so forth.
You might find it interesting that SAS/IML Studio, which has a client-server architecture, handles interrupts differently. Programs that are submitted through SAS/IML Studio check for interrupts more frequently, and therefore are more responsive to user interruptions. This suggests that you might want to use SAS/IML Studio to test and debug your IML program.
Thanks, I think have a much better understanding now. Is it the case that nested loops get compiled as a single unit and therefore can not be interrupted? So the loop slicing trick will only work on the outer most loop?
Now I know the issues, I think I am comfortable managing it myself with call execute. The empty command does work by the way, so if I use:
and then at various points later on:
it should make the purpose clear to others.
Registration is open! SAS is returning to Vegas for an AI and analytics experience like no other! Whether you're an executive, manager, end user or SAS partner, SAS Innovate is designed for everyone on your team. Register for just $495 by 12/31/2023.
If you are interested in speaking, there is still time to submit a session idea. More details are posted on the website.
Learn how to run multiple linear regression models with and without interactions, presented by SAS user Alex Chaplin.
Find more tutorials on the SAS Users YouTube channel.