X

NV5 Geospatial Blog

Each month, NV5 Geospatial posts new blog content across a variety of categories. Browse our latest posts below to learn about important geospatial information or use the search bar to find a specific topic or author. Stay informed of the latest blog posts, events, and technologies by joining our email list!



Mapping Earthquake Deformation in Taiwan With ENVI

Mapping Earthquake Deformation in Taiwan With ENVI

12/15/2025

Unlocking Critical Insights With ENVI® Tools Taiwan sits at the junction of major tectonic plates and regularly experiences powerful earthquakes. Understanding how the ground moves during these events is essential for disaster preparedness, public safety, and building community resilience. But traditional approaches like field... Read More >

Comparing Amplitude and Coherence Time Series With ICEYE US GTR Data and ENVI SARscape

Comparing Amplitude and Coherence Time Series With ICEYE US GTR Data and ENVI SARscape

12/3/2025

Large commercial SAR satellite constellations have opened a new era for persistent Earth monitoring, giving analysts the ability to move beyond simple two-image comparisons into robust time series analysis. By acquiring SAR data with near-identical geometry every 24 hours, Ground Track Repeat (GTR) missions minimize geometric decorrelation,... Read More >

Empowering D&I Analysts to Maximize the Value of SAR

Empowering D&I Analysts to Maximize the Value of SAR

12/1/2025

Defense and intelligence (D&I) analysts rely on high-resolution imagery with frequent revisit times to effectively monitor operational areas. While optical imagery is valuable, it faces limitations from cloud cover, smoke, and in some cases, infrequent revisit times. These challenges can hinder timely and accurate data collection and... Read More >

Easily Share Workflows With the Analytics Repository

Easily Share Workflows With the Analytics Repository

10/27/2025

With the recent release of ENVI® 6.2 and the Analytics Repository, it’s now easier than ever to create and share image processing workflows across your organization. With that in mind, we wrote this blog to: Introduce the Analytics Repository Describe how you can use ENVI’s interactive workflows to... Read More >

Deploy, Share, Repeat: AI Meets the Analytics Repository

Deploy, Share, Repeat: AI Meets the Analytics Repository

10/13/2025

The upcoming release of ENVI® Deep Learning 4.0 makes it easier than ever to import, deploy, and share AI models, including industry-standard ONNX models, using the integrated Analytics Repository. Whether you're building deep learning models in PyTorch, TensorFlow, or using ENVI’s native model creation tools, ENVI... Read More >

1345678910Last
«January 2026»
SunMonTueWedThuFriSat
28293031123
45678910
11121314151617
18192021222324
25262728293031
1234567
19749 Rate this article:
3.8

Why are for loops in IDL so slow?

Anonym

Once upon a time, I worked as an undergraduate programmer, where I wrote code that calculated atmospheric radiation algorithms. Before I knew much about IDL, I wrote some code that performed the desired calculations and placed it inside a giant for loop. To say the least, this code was slow and painful to run. In fact, it was so bad that a guy from IT came into my office to tell me I had to stop using so much of their processors. Not only that, but it took over a day to run code that calculated a day's worth of atmospheric radiation, and the algorithms don't do much good if data comes in faster than it can be processed.

That was when I decided to pick up some IDL books and learn more on how to write better code. As it turns out, there are quite a few ways to move calculations outside of a loop and reduce how much work is done inside the loop.

Why do loops in IDL seem slow?

First of all, this is not unique to IDL. If you don't believe me, look at what people commonly ask Google:

 

IDL is an interpreted language, which is defined by Wikipedia as

 An interpreted language is a programming language for which most of its implementations execute instructions directly, without previously compiling a program into machine-language instructions. The interpreter executes the program directly, translating each statement into a sequence of one or more subroutines already compiled into machine code.

 

This means that when IDL executes a for loop, each statement inside the loop is interpreted at the IDL level and then sent down to the machine to process, and this is done every time the loop iterates. In loops with many, many iterations or when there are several statements inside the loop, the loop will be very slow to complete.

That said, what is the best way to avoid this problem?

Vectorize

Vectorizing, or operating on an entire array at once, is probably the first piece of advice found from the Google search above. Nearly all of IDL's mathematical functions can accept arrays and not just single values, and the result will be a corresponding array. Consider this statement

array = Dindgen(100000, INCREMENT=.001)
arcsines = DblArr(100000, /NOZERO)
for i=0,99999 do arcsines[i] = asin([i])

This loop took 0.047 seconds to run on my computer. However by performing the arcsine operation outside of the loop results in a significant gain.

arcsines = asin(array)

In fact, for me, the time to execute this statement was so small that IDL's tic/toc calls around it reported zero seconds. 

The reason for this is that instead of passing each arcsine call to the machine to execute individually, the whole array is passed at once, and the machine handles the array. In other words, there is only one time IDL and the machine communicate back-and-forth instead of 100000 times.

Additionally, WHERE is (in my mind) one of the most convenient vectorized operations in IDL. Using it can often avoid the need for a loop altogether. The conditional value inside the Where statement can be an array of any dimensions.

result = Where(condition, count)

Keep in mind, also, that if all you care about is the count in the Where call and you don't need the result, you can avoid creating a new variable by using TOTAL on the condition, where the items in the conditional value can also be an array of any dimensions:

count = Total(condition)

Move conditionals and calculations outside of loops

Conditional statements always come with a performance expense. Again, consider vectorization if it is possible to do so, but if not, try keeping conditional statements as simple as possible.

One possibility is if you know you will only work with a subset of data, use a WHERE statement and only iterate through the subset. For example, instead of this:

for i=0,N_Elements(array) do begin
  if (array[i] mod 3 eq 0) then begin
    ...
  endif
endfor

try this:

result = Where(array mod 3 eq 0, count)
for ii=0, count-1 do begin
  i = result[ii]
  ...
endfor

Now you are only doing 1/3 as many iterations of the loop, and the conditional has been moved outside of the loop

Also consider moving mathematical calculations on constants outside of the loop so that minimal operations are performed in the loop. For example, instead of this:

for i=0,N_Elements(array) do begin
  value = array[i] * !pi/2
endfor

try this:

piOverTwo = !pi/2
for i=0,N_Elements(array) do begin
  value = array[i] * piOverTwo
endfor

The loop completed in half of the time when the constants were computed and set to a single variable. Again, try to keep the content of the loop as simple as possible.

Use in-place operations

It is more efficient if you can operate on a variable in-place rather than redefine the variable. In this statement:

var = var + 1

IDL creates a new item in memory, performs the operation, and then forgets about the old item. Inside a large loop, this can be expensive.

IDL contains the following in-place operators:

 Operator  Definition Example  Non in-place Equivalent 
++   Increment variable by one  a++  a = a + 1
 --  Decrement variable by one  a--  a = a - 1
 +=  Add a specified value to a variable (value specified after operator)  a += 2  a = a + 2
 -=  Subtract a specified value from the variable  a -= 2  a = a -2
 *=  Multiply the variable by a specified value  a *= 2  a = a * 2
 /=  Divide the variable by a specified value  a /= 2  a = a /2

 

This can be done to elements of an array in addition to a single variable:

array[i]++

array[i] /= 2

and it can even be done to a whole array (vectorized operation):

array--

array *= 3

Use early breaks if possible

As described in an IDL Data Point post about a year and a half ago, it is convenient to move on to the next iteration of the loop using CONTINUE in cases where it is not necessary to continue with the current iteration of the loop. Also, if there is no more work to do in the loop altogether, then it saves time to exit from a loop early using BREAK. This can be useful if, for instance, you have a way to determine that the rest of the data in your array is missing or unimportant data.

Note that order matters

Lastly, note that IDL is Column-major rather than row-major (just like Fortran, rather than C). Although this code is more intuitive and is what you would write in C:

array = Lindgen(10000,100000)
for i=0,9999 do begin
  for j=0,9999 do begin
    value = array[i,j]/2
  endfor
endfor

This loop took 9.96 seconds to run on my computer. However, by switching i and j:

for j=0,9999 do begin
  for i=0,9999 do begin
    value = array[i,j]/2
  endfor
endfor

it took only 8 seconds to run. This is because when IDL iterates through the columns before iterating through the rows, it is accessing the data in the order in which it is stored in memory.

In conclusion

For loops in IDL can sometimes seem like bad thing, but they aren't really that bad and are sometimes unavoidable. There are quite a few techniques to use that make loops as efficient and fast as possible, and this article outlines only a handful of them. To summarize these:

  • First try vectorization. Move a whole line or even getting rid of the loop altogether if IDL has a way to perform your desired calculation using a single call on the array.
  • Move everything possible out of the loop, such as setting variables, calculating using constants, and performing conditional statements. Consider using the WHERE statement when checking conditionals or looking for a certain item in the array.
  • Use in-place operators for simple arithmetic to avoid making copies of variables or arrays.
  • Leave the loop early if you are done with it.
  • Finally, access data in the order in which it is stored.

The idea, in conclusion, is to keep the loops as simple and minimalistic as possible.

By the way, I only mention for loops in this article. However, these exact same techniques apply to any kind of loop in IDL, including While, Repeat, and Foreach.

 

Please login or register to post comments.