- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Dear Ifort team, in the following program, I ask for 2 assignments. One is using the targets themselves, the other is using pointers instead: program test real(kind=4), target :: a(2),b(2) real(kind=4), pointer :: pa(:),pb(:) ! b = a pa => a pb => b pb = pa ! end program test Quoting this document: https://software.intel.com/en-us/articles/fortran-array-data-and-arguments-and-vectorization "Potential overlap of pointer based variables on the left-hand side (LHS) expression and the right-hand side (RHS) will cause array temporaries to be created to hold the RHS expression as it's evaluated prior to storing to the LHS." There is a temporary array involved in the second (pointer to pointer) assignment. This affects clearly the execution time when using large arrays and/or repeating many times the copy. While the standard says more or less that "you'll get what you deserve" when aliasing actual arguments passed to a procedure, on the other hand it ensures that the assignment works "as expected" with the following rule (Fortran 2003, 7.4.1.3): "The execution of the assignment shall have the same effect as if the evaluation of all operations in expr and variable occurred before any portion of variable is defined by the assignment." So, here is where we stand: 1) the standard says the assignment must work in any case, 2) the LHS and RHS may be aliased when pointers are involved, 3) the compiler introduces a temporary array for safety. Am I correct up to now? So, here is the question: is it possible to avoid this temporary array? I looked at the alias-related compilation options, but they seem all focused on argument aliasing. Or, is there any hope that ifort relaxes the 3rd point above, and that it checks if LHS and RHS actually overlap or not? I would say this is very similar to what is done regarding arrays, contiguity, strides, etc in the document I pointed above. I can also add that in my real use-case: - I need those pointers for other reasons / I can not switch to allocatables, - I always keep in mind efficiency when working with arrays (contiguity, etc), - I would accept to take the responsibility of ensuring non-aliasing of LHS and RHS if the temporary array could be disabled by force e.g. with an option. Thanks, Sebastien
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
>>While the standard says more or less that "you'll get what you deserve" when
aliasing actual arguments passed to a procedure
ergo create an inline subroutine to perform the copy (and hope the optimizer does not thwart your intentions).
Jim Dempsey
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
!dir$ simd sometimes suppresses creation of a temporary array. ifort 15.0 took care of a few cases where this was needed on a DO loop.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
jimdempseyatthecove wrote:Indeed, that is one of the options I tested. But this means that if I want to keep my code efficient I have to replace all my assignments involving pointers by a copy subroutine. This is just crazy!
ergo create an inline subroutine to perform the copy (and hope the optimizer does not thwart your intentions).
Tim Prince wrote:This is a compiler specific syntax... I am willing to find either a Fortran-standard solution, or a per-compiler global solution (option). Both of your suggestions imply editing all of my assignments involving pointers and use something specific. This seems hard to maintain for me and my current and future co-workers. I was looking more for a general solution from the compiler itself.
!dir$ simd sometimes suppresses creation of a temporary array. ifort 15.0 took care of a few cases where this was needed on a DO loop.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Where you have a pointer that is known to not alias, you could redefine the variable to be user defined type, containing only the pointer and an assignment operator. Then your source could contain.
pa = pb
And behind the scenes you call the copy function.
However, this may come at the expense of requiring pa%p => targetedArray
Though this may also be addressed by use of a second assignment operator (one for like pointer, another for type of array it points to).
Jim Dempsey
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I have submitted some cases to Intel premier support where ifort requires the proprietary !dir$ simd to accomplish a result which gfortran accomplishes with !$omp simd. For the latter (OpenMP 4 standardized) directive, you need newer compilers. One of the objectives for OpenMP 4, which Intel supported, was to cut down on these differences among compilers. Still, Intel compilers frequently rely on directives to achieve superior performance.
Global optimization flags aren't satisfactory if they imply risking failure of standard-compliant code. Enough flak comes from customers whose code breaks due to violations of standard which weren't exposed before.
The improvement which I mentioned in the ifort 15 release indicates that Intel isn't necessarily insisting on continuing use of proprietary directives where they can be made redundant. The situation is confused by the slogan about directive based vectorization in the publicity about the newer releases.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
jimdempseyatthecove wrote:This seems an interesting path, but I think that accessing the actual data as pa%p will make things worse everywhere else. Or then I have to redefine all the other methods which I need. This seems costly and dangerous...
Where you have a pointer that is known to not alias, you could redefine the variable to be user defined type, containing only the pointer and an assignment operator. Then your source could contain.
pa = pb
And behind the scenes you call the copy function.
However, this may come at the expense of requiring pa%p => targetedArray
Though this may also be addressed by use of a second assignment operator (one for like pointer, another for type of array it points to).
Jim Dempsey
I also realized that Fortran 2008 allows me to provide a "defined assignment", but unfortunately I am not allowed to redefine the assignment for 2 arrays of same type, kind and rank. Too bad.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
You also must be mindful that at some future time, you or your successor might be (forced into) using
pa => NonContiguousArraySection(From:To:Stride)
And then your efforts to avoid the temporary copy on pb = pa will come back and bite you (them).
If you use the user defined type with assignment operator(s), you could examine the array descriptor for stride. For stride of 1 you could then do the equivalent of the memcopy, for other strides use cell by cell copy.
Jim Dempsey
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
>> since 2 contiguous pointers can still alias each other
However, they (contiguous pointers) are also guaranteed to have a stride of 1. In the general case, pointers may have non-1 strides.
Jim Dempsey
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
jimdempseyatthecove wrote:I do not see the point. Here is where we stand: - while contiguity does not ensure non-aliasing, the compiler checks if it worth adding a temporary array in between CONTIGUOUS pointers, - but on the other hand, non-aliased non-CONTIGUOUS pointers do not benefit this optimization. As far as I understand, if stride is known to be 1 at compilation time, the temporary array may be disabled (non-aliasing still must be checked at runtime!), but if stride-1 is not known at compilation time, the optimization is just dropped off. Is it a problem to check for stride-1 at run time, and fall back to the same optimizations as the CONTIGUOUS pointers case?
>> since 2 contiguous pointers can still alias each other However, they (contiguous pointers) are also guaranteed to have a stride of 1. In the general case, pointers may have non-1 strides.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I don't think that we do a run-time check for assignments. Currently we do this only when passing assumed-shape arguments to a routine that wants a contiguous array.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Sebastien,
While I agree with you that code could (should) be added to test to see if a temporary can be avoided (when beneficial), this is apparently an optimization request that is low on the list of feature requests (list ranking made by compiler developers).
I would like to point out that a lot of optimization effort went in to generating code to auto-test and perform peel and loop remainder operations to enhance vectorization. It should be easier to perform overlap and/or contiguity tests and then choose the best of several copy (construct) strategies.
Jim Dempsey
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page