Vectorization Lab Fortran Problem

Vectorization Lab Fortran Problem

Hi,

i downloaded Intel Vectorization Lab Session (Fortran Version) and i have a problem compiling example of elemental function (file: vectorization_elem_funct_directive.f90).

I receive this error:

[pierpaolo@imip1 vectorization_lab_Fortran]$ ifort vectorization_elem_funct_directive.f90 -o vectorization_elem_funct_directive
vectorization_elem_funct_directive.f90(121): error #6634: The shape matching rules of actual arguments and dummy arguments have been violated.   [RESULTS]
        call do_multiply( results(j*arows:(j+1)*arows-1),&
--------------------------^
vectorization_elem_funct_directive.f90(122): error #6634: The shape matching rules of actual arguments and dummy arguments have been violated.   [A]
          & a(k*arows:(k+1)*arows-1), b(j*brows+k))
------------^
compilation aborted for vectorization_elem_funct_directive.f90 (code 1)

If i comment interface 'do_multiply' in subroutine 'gemm', everything works fine, but i don't understand why. 

Any suggestion?

Thanks in advance

Pierpaolo

16 posts / 0 new
Last post
For more complete information about compiler optimizations, see our Optimization Notice.

Where did you find the source code download for this?

It looks as if some syntax checking was missing or disabled at the time the exercises were set up, so it may be a bug in the example provided.  In the MIC cross compiler for linux, some such checking is enabled by -warn interfaces (for the case where the explicit interface isn't found).

I would have thought the error message would point to an explicit interface which disagrees with the procedure calls, but you didn't show that.

Hi,

i found source code from here (Vectorization - Fortran): https://software.intel.com/en-us/articles/intelr-xeon-phitm-advanced-workshop-labs

Thanks for your reply

Pierpaolo 

I see in the comments that correcting the interface blocks is left as an exercise to the reader.  I see the same error as you quoted.

This interaction between attributes vector and interface checking in current compilers seems mysterious.

I never did see the promised documentation of recommendations about this ifort elemental feature should be used (distinct from the Fortran standard elemental).  Apparently, the thinking, or at least the treatment by the compiler, has changed since the examples were posted.

I'll file a premier issue: 6000057067 asking for explanation if this directive has been withdrawn or replaced.

Tim,

Thanks
--
Taylor
 

Hi,

Thanks for everything.

Pierpaolo

I can get the example to work by replacing DEC$ ATTRIBUTES VECTOR with !$OMP DECLARE SIMD, but that should not be necessary.  I'll check with the Fortran front-end team.

Patrick

This document was quoted as current:

https://software.intel.com/en-us/articles/explicit-vector-programming-in...

I'm not able to confirm that such changes can make the case compile.

"SIMD-enabled" has been put forth as a terminology for procedures designated in OpenMP 4 by !$omp declare simd which Intel formerly called simd elemental.

Support of this "explicit vector programming" slogan was put forward as a primary goal for Intel compilers, but I haven't found it working consistently, not only because non-Intel compilers don't interpret the simd clause as setting equivalents of VECTOR ALWAYS (e.g. gfortran -ffast-math).   So it continues to be necessary to compare results with directives and by setting compiler options without directives.

 

It was too confusing to call SIMD-enabled procedures/functions 'simd elemental' due to ELEMENTAL being a Fortran keyword.

I did a quick hack of vectorization_elem_funct_directive.f90, which I need to further examine to understand some oddities, but the key change was to switch to !$omp declare simd.  I'm reluctant to describe the hacks without better understanding, but I do think there is a compiler issue with !dir$ attributes vector :: do_multiply

pbkenned@dpdknf01:~/misc/Fortran/vectorization_lab_Fortran$ ifort -V
Intel(R) Fortran Intel(R) 64 Compiler XE for applications running on Intel(R) 64, Version 14.0.3.174 Build 20140422
Copyright (C) 1985-2014 Intel Corporation.  All rights reserved.

pbkenned@dpdknf01:~/misc/Fortran/vectorization_lab_Fortran$ ifort -openmp vectorization_elem_funct_directive.f90 && ./a.out
 Duration:   0.5775000     secs
pbkenned@dpdknf01:~/misc/Fortran/vectorization_lab_Fortran$

 

Patrick

!dir$ attributes vector :: some_procedure is broken.  The tracking number is DPD200243379, to which I will attach this thread.

I'm reluctant to describe the following hacks I made to get this working (I'll be creating new problem reports for the developers for compiler deficiencies), but here goes:

1) The strangest one:

< end subroutine do_multiply
---
> end subroutine dmultiply
 

The parser is treating 'do_multiply' as the start of a DO loop, and a whole cascade of weird errors is puked forth.  So, all instances of 'do_multiply' have been changed to 'dmultiply'

2) < !dir$ attributes offload : mic :: do_multiply
< !dir$ attributes vector :: do_multiply
< subroutine do_multiply(r,a,b)
---
> !dir$ attributes offload : mic :: dmultiply
> subroutine dmultiply(r,a,b)
> !$omp declare simd(dmultiply)
 

As mentioned previously, this is the key change; use !$omp declare simd(dmultiply) in place of !dir$ attributes vector :: do_multiply
 

3) Remove the interface spec from subroutine gemm().  Otherwise, we're back to 'The shape matching rules of actual arguments and dummy arguments have been violated.'  And for the interface spec, it is NOT a workaround to substitute the OMP directive.  In other words, this is NOT a workaround:

  interface
    subroutine dmultiply(r,a,b)
    !$omp declare simd(dmultiply)
    real(8), intent(inout) :: r
    real(8), intent(in) :: a,b
    end subroutine dmultiply
  end interface
 

With the above changes, the code compiles and run normally on a Phi coprocessor system, using ifort-14.0.3:

pbkenned@dpdknf01:~/misc/Fortran/vectorization_lab_Fortran$ ifort -openmp -vec-report vectorization_elem_funct_directive.f90
vectorization_elem_funct_directive.f90(55): (col. 8) remark: LOOP WAS VECTORIZED
vectorization_elem_funct_directive.f90(56): (col. 8) remark: LOOP WAS VECTORIZED
vectorization_elem_funct_directive.f90(122): (col. 10) remark: LOOP WAS VECTORIZED
vectorization_elem_funct_directive.f90(122): (col. 10) remark: LOOP WAS VECTORIZED
vectorization_elem_funct_directive.f90(80): (col. 3) remark: LOOP WAS VECTORIZED
vectorization_elem_funct_directive.f90(92): (col. 3) remark: LOOP WAS VECTORIZED
vectorization_elem_funct_directive.f90(94): (col. 5) remark: LOOP WAS VECTORIZED
vectorization_elem_funct_directive.f90(104): (col. 12) remark: FUNCTION WAS VECTORIZED
vectorization_elem_funct_directive.f90(104): (col. 12) remark: FUNCTION WAS VECTORIZED
vectorization_elem_funct_directive.f90(94): (col. 5) remark: *MIC* LOOP WAS VECTORIZED
vectorization_elem_funct_directive.f90(104): (col. 12) remark: *MIC* FUNCTION WAS VECTORIZED
vectorization_elem_funct_directive.f90(104): (col. 12) remark: *MIC* FUNCTION WAS VECTORIZED
pbkenned@dpdknf01:~/misc/Fortran/vectorization_lab_Fortran$ ./a.out
 Duration:   0.5792000     secs
pbkenned@dpdknf01:~/misc/Fortran/vectorization_lab_Fortran$
 

Patrick

I had to change the compile and link command from what I found with MKL Link Advisor (on web; the one in my installation seems more broken):

ifort  -qopenmp -I$MKLROOT/include/intel64/lp64 -I$MKLROOT/include  -qoffload-attribute-target=mic -qoffload-option,mic,compiler,"  $MKLROOT/lib/mic/libmkl_blas95_lp64.a -Wl,--start-group $MKLROOT/lib/mic/libmkl_intel_lp64.a $MKLROOT/lib/mic/libmkl_core.a $MKLROOT/lib/mic/libmkl_intel_thread.a -Wl,--end-group" vectorization_direct.f90

or, more briefly,

ifort  -qopenmp  -qoffload-attribute-target=mic   $MKLROOT/lib/mic/libmkl_blas95_lp64.a -mkl vectorization_direct.f90

Running on over 2 year old KNC B0:

 Duration:   0.4337000     secs

Offload and native mode are the same.

Unfortunately, for comparison,  running on Xeon 5690 host:

 Duration:   3.8999999E-03 secs

 

Today's response from the compiler team on my problem report confirms that "SIMD-enabled" procedures do not yet support array arguments. 

Maybe it has been an accident when the example appeared to work.  It's a little strange to have an example distributed without identifying it as intended future functionality.

I'm afraid I am responsible for the Fortran code in this lab. But I did test the code before I posted it - honest I did. 

When this code was posted, it compiled and ran as written. That doesn't necessarily mean it was doing what I thought it was doing. There are some differences between the treatment of standard elemental functions and vector simd functions that I did not realize at the time I wrote this code. But, regardless, it did compile and run without error. And based on what Martyn said in his article (the one Tim pointed to as being current), the code should still run. But apparently a) Tim was just told by the developers that it shouldn't work and b) it doesn't work now.

So, what am I going to do about this? Well, tomorrow I will check out the C version of the lab and make sure it still works. Then I will see about either pulling this lab, at least until the compiler doesn't interpret do_multiply as the start of a do loop and is able to handle array sections as arguments to the function, or modifying the code.

As for the comment in the code about modification of the interface being left as an exercise to the reader, that was actually referring to the possibility of further modifying the code to mimic the C templates that were used in the C version of this lab. Mimicking C templates is possible, but ugly. Hence, left as an exercise to the reader.

And this is just an aside - a comment that actually has nothing to do with the main problem. Patrick found that the compiler was treating do_multiply as the start of a do loop. I know of nothing in the standard - even the more recent versions - that would allow for this interpretation. So I am hoping that the response to Patrick's problem report will come back as "Whoops, we should fix that" and not "Boy, why would you even try to use a name like that." But in any event, it reminds me of a bug that sometimes crept into Fortran programs back in the good, old days.

In the good, old days, Fortran ignored spaces between characters within the code. And there were (and I believe still are) no keywords in Fortran. This meant that 'do i = 1, 100' was the same to any Fortran compiler as doi=1,100' and the compiler knew that this was a do loop because of that comma between the 1 and 100. But what happened if you accidentally left out that comma? Well the compiler would then interpret 'do i = 1 100' as being a variable named doi being set to the value of 1100, which the compiler didn't like because the name doi was, by default, the name of a real (i.e. a floating point) number. So all you users of more "modern" languages (including the latest versions of Fortran) can have a little laugh about this but .... I still like good, old Fortran the best.

A slightly worse case is replacing the comma in the DO loop with a period.  This is also interpreted as an assignment statement and is even harder to visually distinguish from the desired text  -- especially for folks from countries that use commas and periods in numbers differently than the U.S. standard.

John D. McCalpin, PhD "Dr. Bandwidth"

Hello Frances,

Thanks for sharing the history of the code, it sheds new light on the issue (at least for me).  I think it is worth repeating what the originator of this thread said: "If i comment interface 'do_multiply' in subroutine 'gemm', everything works fine, but i don't understand why."

Well, neither do we.  And indeed it is the case, if you remove the interface definition of do_multiply() from the caller gemm(), vectorization_elem_funct_directive.f90 compiles and produces a SIMD vector version of do_multiply() that runs just fine on a Phi system.

However, it not really safe or desired that one leaves out the interface spec, and you shouldn't have to 'dummy-down' the code to vectorize the function.  In fact, the original test case attached to DPD200243379 has a similar interface definition, and provokes the same 'shape matching rules...violated' error.  Remove the interface, and it compiles just fine.  So that is the blocking error we are fixing.

Regarding the interpretation of 'do_multiply()' as the beginning of a do loop, now I realize this error was due to me substituting '!$omp declare simd(do_multiply)' for '!dir$ attributes vector :: do_multiply'.

First I had removed the interface, and confirmed what the original poster said.  That compiled and ran fine, so I thought I would just take a moment to verify that substitution of the omp directive produces the same results.  Well, that simple substitution provoked a whole cascade of parsing errors starting with !$omp declare simd(do_multiply) -- including treating the 'do_' as an invalid 'do' construct with an illegal underscore:

pbkenned@dpdknf01:~/projects/ISN_Forums/U517797/vectorization_lab_Fortran$ ifort vectorization_elem_funct_directive.f90 -openmp
vectorization_elem_funct_directive.f90(108): error #5192: Lead underscore not allowed
!$omp declare simd(do_multiply)
------------------------------^
vectorization_elem_funct_directive.f90(108): error #5082: Syntax error, found 'DO' when expecting one of: <IDENTIFIER>
!$omp declare simd(do_multiply)

 

So there are really several issues to untangle with all this.  All DPD200243379 is going to fix is the rejection of the interface spec that breaks compilation.  There is no progress to report on DPD200243379, and I am trying to get some indication from the developers we plan to fix this.  I'll keep this thread updated with any developments.

Patrick

The numerous issues raised in this thread appear now to all be resolved in IPS Composer XE 2015 update #2, so I am closing this ticket now.

Specifically, the issue raised in DPD200243379 was closed as a misunderstanding about the definition of Fortran ELEMENTAL versus the optimizer's handling of Intel-defined vector functions.  Regarding the error about violating the shape matching rules, when the actual argument is an array section, the compiler passes a descriptor specifying the bounds, stride, etc, so the error is correct:

[U517797]$ ifort -c vectorization_elem_funct_directive.f90
vectorization_elem_funct_directive.f90(123): error #6634: The shape matching rules of actual arguments and dummy arguments have been violated.   [RESULTS]
        call do_multiply( results(j*arows:(j+1)*arows-1),&
--------------------------^
vectorization_elem_funct_directive.f90(124): error #6634: The shape matching rules of actual arguments and dummy arguments have been violated.   [A]
          & a(k*arows:(k+1)*arows-1), b(j*brows+k))
------------^
compilation aborted for vectorization_elem_funct_directive.f90 (code 1)

On the other hand, if the actual argument is an array or array element, the compiler just passes the starting address.  Considering the original interface for subroutine do_multiply():

  interface
    subroutine do_multiply(r,a,b)
    !dir$ attributes vector :: do_multiply
    real(8), intent(inout) :: r
    real(8), intent(in) :: a,b
    end subroutine do_multiply
  end interface
 

It might work to define the array dummy arguments so that the subroutine expects descriptors:

real(8), intent(in), dimension(:)  :: a

real(8), intent(inout), dimension(:)  :: r

However, there is a better solution, IMHO, which is to define subroutine do_multiply() as Fortran elemental.  Fortran ELEMENTAL functions are defined with scalar arguments – they handle array arguments {that follow certain rules} by expanding the elemental function call into a loop calling the scalar function with each set of elements of the array arguments. That’s the way Fortran Standard ELEMENTAL functions work.  Once there is a loop {from the user or from ifort}, the optimizer can work its magic.  That magic includes !dir$ attributes vector :: procedure.

 

So all of this just boils down to defining the procedure as Fortran elemental:

!dir$ attributes offload : mic :: do_multiply
!dir$ attributes vector : uniform(b) :: do_multiply
elemental subroutine do_multiply(r,a,b)
  real(8), intent(inout) :: r
  real(8), intent(in) :: a,b
  r = r + a*b
end subroutine do_multiply
 

Note I've also indicated scalar 'b' as uniform as an aid to the optimizer. This now compiles and runs error-free:

[vectorization_lab_Fortran]$ ifort -V
Intel(R) Fortran Intel(R) 64 Compiler XE for applications running on Intel(R) 64, Version 15.0.2.164 Build 20150121
Copyright (C) 1985-2015 Intel Corporation.  All rights reserved.

[vectorization_lab_Fortran]$ ifort vectorization_elem_funct_directive.f90 -o vectorization_elem_funct_directive.f90.x
[vectorization_lab_Fortran]$ ./vectorization_elem_funct_directive.f90.x
 Duration:    1.491800     secs
[vectorization_lab_Fortran]$

 

Patrick

 

 

Login to leave a comment.