Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.

Array temporary created ?

lee_bassom
Beginner
3,381 Views

I'm hooping someone can help me with the following problem.

I am getting the following error message and have been unable to track down any information about what it means.
I am passing a subset of an array to a subroutine and getting this message everytime I call the subroutine.

"%FOR-W-DIAGNOSTIC, Message number 135266304, In call to XXXXX, an array temporary was created for argument #1"

Any help/suggestions much appreciated.

0 Kudos
12 Replies
Steven_L_Intel1
Employee
3,381 Views
It is not an error message - it is a warning that you enabled by selecting tie option /check:arg_temp_creation (or the equivalent in the IDE.) It is there to let you know that, because of the way you coded your program, the compiler has to make a copy of an array argument before passing it, a performance degradation. You shoukd try to eliminate these copies by making sure you don't pass non-contiguous arrays to routines that don't accept arrays by descriptor.
0 Kudos
lee_bassom
Beginner
3,381 Views
Thanks for the help :)
How would I go about fixing this ?
The call is:
CALL routine(array(33:48))
and routine is defined as follows:
SUBROUTINE routine(array)
IMPLICIT NONE
REAL*4 array(16)
......
END SUBROUTINE
0 Kudos
Steven_L_Intel1
Employee
3,381 Views
What is the declaration of ARRAY in the caller? Is it a deferred-shape array that points to a non-contiguous section? The compiler detects at run-time whether a copy is needed, so the message suggests that this is so.
0 Kudos
lee_bassom
Beginner
3,381 Views
ARRAY is defined asREAL*4 ARRAY(1:48)
The subroutine only needs the back end of the array which is why I was just passing a subsection.
Lee.
0 Kudos
Jugoslav_Dujic
Valued Contributor II
3,381 Views
Which version of CVF is that? You can download 6.6C3 patch here.
I'm not sure about the current state of the art -- Steve indicates that contiguity test is now performed at run-time -- but earlier versions had troubles recognizing when "copy-in/copy-out" is really necessary, sometimes doing it when it wasn't needed.
In any case, a method which will certainly work (provided that ARRAY is really contiguous) is if you just put
ARRAY(33)
instead of
ARRAY(33:48)
as actual argument. This is legal, and you already ensure that you reference only 16 elements of the array, so no bounds will be exceeded.
Jugoslav
0 Kudos
lee_bassom
Beginner
3,381 Views
On a legacy system using Fortran90.
Can't do ARRAY(33), that would just pass the 33rd element to the subroutine.
Has to be ARRAY(33:48) to pass the 33rd to 48th elements.
Lee
0 Kudos
Jugoslav_Dujic
Valued Contributor II
3,381 Views
No. Although it's part of "F77" legacy, it's still perfectly valid & legal to pass just an array element as actual argument for an assumed-size or explicit-shape dumy (the latter is your case). In such cases, the address of the array element is passed, and the callee treats it as the first element of the dummy argument array. It is not legal to pass an array element to an assumed-shape dummy.
As a rule of thumb, avoid passing array sections (which are part of F90-standard) to assumed-size or explicit-shape dummy arguments. CVF should get it right, and the following code demonstrates that (but either you have an older version or your actual code is more complicated than that). Note that in 3rd case the actual argument is really discontiguous and a temporary copy must occur:
Code:
PROGRAM Assumed

REAL::      Array(48)
INTEGER::   k

Array = (/(k, k=1,48)/)
CALL sub(Array(33))
CALL sub(Array(33:48))
CALL sub(Array(15:48:2))

CONTAINS

SUBROUTINE Sub(Arr)
REAL::      Arr(16)
WRITE(*,"(4F4.0)") Arr
WRITE(*,*) "------------------"
END SUBROUTINE Sub

END PROGRAM Assumed

OUTPUT:
 33. 34. 35. 36.
 37. 38. 39. 40.
 41. 42. 43. 44.
 45. 46. 47. 48.
 ------------------
 33. 34. 35. 36.
 37. 38. 39. 40.
 41. 42. 43. 44.
 45. 46. 47. 48.
 ------------------
forrtl: warning (402): fort: (1): In call to SUB, an array 
temporary was created for argument #1

 15. 17. 19. 21.
 23. 25. 27. 29.
 31. 33. 35. 37.
 39. 41. 43. 45.
 ------------------
Jugoslav
0 Kudos
hdankowski
Beginner
3,381 Views

Hi,

The suggested solution with sub(array(33)) does not work if modern features like interfaces to overload routines are used.

An example is given below.

1. If the source code is compiled with call test_ta(17,b(1,32)) the following error is given

test_tmparray.f90(58): error #6285: There is no matching specific subroutine for this generic subroutine call.   [TEST_TA]

(It works for the second call test_ta_s(17,b(1,32))!)

2. If the call is changed to call test_ta(17,b(1,32:48)), the code compiles but the runtime warning is issued!

forrtl: warning (402): fort: (1): In call to TEST_TA_S, an array temporary was created for argument #2

So either a compile error or a runtime warning is received. I think the compiler should not issue a warning in this case, because it will probably only pass the first adress and the size and should not create a tmp array.

Hendrik

0 Kudos
Steven_L_Intel1
Employee
3,381 Views

Regarding the compile-time error - I agree that this is a compiler bug and I will let the developers know. The compiler is evidently not taking sequence association into account when doing generic resolution.

As for the run-time warning, you are forgetting (or are perhaps unaware) that Fortran stores arrays in "column-major" order so that the leftmost subscript changes the fastest. Your array section b(1,32:48) is NOT contiguous. You probably want to reverse the order of the subscripts. Even if the compiler allowed the first call, it would not do what you expect, since the element following b(1,32) is b(2,32), not b(1,33).

0 Kudos
TimP
Honored Contributor III
3,381 Views

"array section b(1,32:48) is NOT contiguous"

In that case, the creation of a temporary stride 1 array would be an optimization if the subroutine reads it repeatedly, particularly in a context which enables vectorization.

The Fortran 77 case of passing the first array element to the procedure could be used to avoid the copy, but the procedure would need to show the stride explicitly (F77 style).

In addition to limitations previously mentioned on combining F77 and array syntax, ifort MIC offload doesn't accept the F77 method of passing an array section by naming the first element.  It's necessary to set a POINTER (in principle, requiring TARGET attribute on the actual array) and pass that in the call.

0 Kudos
jimdempseyatthecove
Honored Contributor III
3,381 Views

integer, parameter :: m=100
real :: b(3,m)
...
call test_ta(17,b(1,32:48))

Must create a temporary array. test_ta, as written, requires dummy a(n) to be contiguous, b(1,32:48) does not specify contiguous memory (it has a stride of 3). Memory for b is organized:

(1,1), (2,1), (3,1), (1,2), (2,2), (3,2), ...

Your call specifies (bold):

(1,32), (2,32), (3,32), (1,33), (2,33), (3,33), (1,34), (2,34), (3,34), ...

If you want to avoid creating temporary .AND. pass strided arguments then in test_ta_s

real :: a(:) ! use assumed shape to permit strided arguments without temporary copy

Jim Dempsey

0 Kudos
Steven_L_Intel1
Employee
3,381 Views

It turns out that I missed seeing a key part of the Fortran standard when I said that the compile-time error was incorrect, Sequence association does not participate in generic resolution. The standard says:

If the procedure is nonelemental and is referenced by a generic name or as a defined operator or defined assignment, the ranks of the actual arguments and corresponding dummy arguments shall agree.

While you can call the specific function with an array element, you can't call a generic and expect it to resolve to a specific that accepts an array argument.

0 Kudos
Reply