Dear Intel FORTRAN Support,
I am using Intel Visual FORTRAN Composer XE 2011 on Windows 64-bit. I would like, if possible, to be able to pass a vector into a subroutine by value as opposed to reference. I would like to know if there is a way of doing this like in C, i.e., being able to control passing by reference or by value. From what I have read, it appears that for scalars, I can use the VALUE attribute but this is not valid for arrays. Is there a way of using the C bindings as a work around to this?
Now, that said, if one can pass by value, is the compiler creating a work array in memory to store a copy of what is being passed? Would I "save any memory" passing by value as opposed to making a work array copy and passing that as opposed to my actual array?
Thank you very much for your help.
Sometimes, the compiler may make a copy of an array section that is to be used as an actual argument, and pass the copy by reference. It is more likely to do so if the array section is of non-unit stride.
To pass a vector having a large number of components by value would involve several major obstacles. Now, if you know that the number of components will always be three, or always four, you can pass them by value or reference as you do any arguments, but if the number is large and/or the number is known only at run time, it will not be so easy.
Thank you for your reply. I guess I will stay with my "work array" solution where I copy the contents and pass the copy into the subroutine. Not the same as using C or Matlab but it does the job!
You're actually wasting memory and CPU cycles passing "by value". When you do this, a copy of the array values are put on the stack in the argument list passed to the routine, just as in C. Consider that for a 10 element array, the compiler has to make space on the stack for 10 elements and then copy the current values to the newly allocated space. When you pass by reference, just a single address is passed.
You can give the VALUE attribute in an explicit interface to an array argument and a copy will be passed. (This is not supported if you use BIND(C)).
At least, this is how it's SUPPOSED to work. I am finding that it doesn't work right, though, and will file a bug report.
In Fortran the programmers (mecej4 and Steve for example) interpret the term vector as analogous to an array (I'm being liberal with this).
To the C/C++ programmer, often, but not always, the term vector relates to the SIMD vector. I will assume here that when you asked pass vector by value, that you were referring to SIMD vector as C/C++ will not pass a vector by value if it is not a SIMD conformable vector. True C/C++ can pass some blob (vector) by value but by only pushing it on stack and formulating a reference to it (this does not seem to be the intent of your original query).
Fortran has support for a vector function:
real function foo(a, b) !dir$ attributes vector :: foo implicit none real, intent(in) :: a, b foo = a + b end function foo
The above function has restrictions on it (see User and Reference Guide). The example above is likely to pass a, and b by value in SIMD registers (4, 8, or 16 reals depending on architecture) and through IPO is likely inlined.
Dear Steve and Jim,
Thank you very much for your replies. First of all, Jim, I think I may have been a little vague here. I refer to a vector as a 1d array and a matrix as a 2d array, i.e., my vector would be, for example, A = [1, 2, 3, 4, 5]. Steve, you verified what I was thinking, i.e., if I pass an array (not a scalar) by value, the compiler would first make a copy and send that to the subroutine. This would be done using the stack memory. This is something that I am trying to avoid. I am writing a fairly large computational EM code that uses lots of memory and large sized arrays. It sounds like the only difference between passing by value and my solution of allocating a work array is that I use memory on the heap(?) (or maybe I should say, not on the stack) but I still need to copy the data from my original vector to the allocated work vector. Doing my way, I can monitor the amount of memory being used and use the STAT = ier in the allocate command and can do something different if I run out of memory.
Thank you both very much for your help.
Assume you have three large allocatable arrays C, A and B (same size for this example)
DO I = 1, SIZE(A)
C(I) = foo(A(I), B(I))
And using the foo function listed in #5 (assuming A, B, C meet the alignment requirements), on a system with AVX2, that loop would process 8 reals per function call (loop may unroll too performing 8xunroll count), call being inlined.
The comment in Quote #3 about C and Matlab is amusing: C doesn't have arrays (until C99, sort of) so it always passes a pointer to a 1-d array by value, effectively passing the array by reference. Matlab always passes copies of its arrays, at least to other Matlab functions.