I have been optimizing some Fortran code that involved searching for an integer value in an unordered array (we know the value occurs only once). Since there is no intrinsic procedure to accomplish this, I thought I’d try a couple of approaches to see which was fastest. The simple answer is that, in this case, brute force beats elegance, even when the target value is near the end of the array.
Download the full example from GitHub
Method 1: Brute force
Algorithm: use a do loop to iterate through the array until you find the target value. Exit the loop when you find the value.
do i = 1, num_elements if (array1(i) .eq. target_value) then loc = i exit endif end do
Results: CPU time required my PC: 0.048 sec
Method 2: forall
Algorithm: use a forall loop to compute the absolute value of the difference between the target value and each value in the array, and store the result in a temporary array. Then use the minloc intrinsic procedure to return the index of the minimum value of the temporary array.
forall (i=1:num_elements) array2(i) = abs(array1(i) - target_value) loc = minloc(array2, 1)
Results: CPU time 0.248 seconds
Method 3: Intrinsic Procedures
Algorithm: use a standard arithmetic operator to compute the difference between each element of the array the the target value, use the abs procedure to compute the absolute value, and use the minloc procedure to find the index of the minimum element.
loc = minloc(abs(array1 - target_value), 1)
Results: CPU time 0.172 seconds
Although the third method appears to be the most elegant, it is quite slow. A simple for loop is orders of magnitude faster, even when it is “penalized” by searching for a value near the end of the array. This is very different from Python (especially NumPy arrays), where it is generally much faster to use NumPy functions than to iterate over arrays.