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

Is there a chance to vectorize the "if-else" condition using omp simd function vectorization?

Bobby_G_
Beginner
376 Views


I am working with these codes (as I post below 2 codes: the original and with omp simd function vectorization). This is the original code, that I want to vectorize:

    PROGRAM TEST
      IMPLICIT NONE
      REAL(KIND=8), DIMENSION(2000):: A,B,C
      REAL(KIND=8)::TIME1,TIME2  
      INTEGER::I,K
    
         !Initial condition    
         !$OMP SIMD           !This part of course could be vectorized
          DO I=1, 2000        !even without !$OMP SIMD statement  
             A(I)=2.0+I/100	  
             B(I)=1.0+I/200
             C(I)=0.2+I/500		 	 
          END DO	  
         !$OMP END SIMD
    	  
        CALL CPU_TIME(TIME1)
     
        DO K=1, 1000000
           !$OMP SIMD              !This part which I want to vectorize 
            DO I=1, 2000           !but of course it was not, since
               IF(A(I)>0.0) THEN   !if-else statement exists
                  C(I)=A(I)+B(I)              		      
               ELSE
                  C(I)=2.0*I		   
               END IF		   
            END DO
           !$OMP END SIMD		  
        END DO	   
     
        CALL CPU_TIME(TIME2)
    
        PRINT *, 'C(2000)           = ', C(2000) 
        PRINT *, 'Elapsed real time = ', TIME2-TIME1, 'second(s)'
    END PROGRAM TEST

I know when the "if-else" statement exists, the compiler couldn't do the auto-vectorization, and in my case it also didn't work even I've put !$OMP DO SIMD, which is clear. And also to my knowledge only the intrinsic function could be vectorized automatically by the compiler. A few days ago, I just read a presentation which there is a chance to vectorize a function using "OMP SIMD FUNCTION VECTORIZATION". So I try changing the original code as below:

    PROGRAM TEST
      IMPLICIT NONE
      REAL(KIND=8), DIMENSION(2000):: A,B,C
      REAL(KIND=8)::TIME1,TIME2
      REAL(KIND=8), EXTERNAL::VEC  
      INTEGER::I,K
   
         !Initial condition    
         !$OMP SIMD       
          DO I=1, 2000
             A(I)=2.0+I/100	  
             B(I)=1.0+I/200
             C(I)=0.2+I/500		 	 
          END DO	  
         !$OMP END SIMD
    	  
        CALL CPU_TIME(TIME1)
    
        DO K=1, 1000000
           !$OMP SIMD  
            DO I=1, 2000 
               C(I)=VEC(A(I),B(I),I)		   
            END DO
           !$OMP END SIMD		 
        END DO	   
     
        CALL CPU_TIME(TIME2)
    
        PRINT *, 'C(2000)           = ', C(2000) 
        PRINT *, 'Elapsed real time = ', TIME2-TIME1, 'second(s)'
    END PROGRAM TEST
    
    FUNCTION VEC(IN1,IN2,IN3) RESULT(OUT1)
     IMPLICIT NONE
     REAL(KIND=8)::IN1,IN2,OUT1
     INTEGER::IN3 
    
              !IN1 = A(I)
              !IN2 = B(I)
              !IN3 = I  
    		  
         !$OMP DECLARE SIMD(VEC)    
               IF(IN1>0.0) THEN
                  OUT1=IN1+IN2              		      
               ELSE
                  OUT1=2.0*IN3		   
               END IF		   
    END FUNCTION VEC

but the vectorization still didn't work. Do you have any idea, how could I vectorize with this !$OMP SIMD? Or it also couldn't be vectorized (it's just a same case with the failure of auto vectorization by the compiler when non-intrinsic function exists)? Any helps will be appreciated. Thanks in advance.

0 Kudos
1 Reply
TimP
Honored Contributor III
376 Views

You didn't update this consistently when you edited it from the version you asked on stackoverflow. Did my comments appear there?

However, it's hard to guess how you could miss.  I don't have a Linux box here, but:

ifort -Qopt-report4 -align:array32byte -Qopenmp-simd bobby.f90

   LOOP BEGIN at C:\users\tim\tim\tim\src\net\bobby.f90(20,13)
      remark #15388: vectorization support: reference C(I) has aligned access
[ C:\users\tim\tim\tim\src\net\bobby.f90(22,19) ]
      remark #15388: vectorization support: reference A(I) has aligned access
[ C:\users\tim\tim\tim\src\net\bobby.f90(22,24) ]
      remark #15388: vectorization support: reference B(I) has aligned access
[ C:\users\tim\tim\tim\src\net\bobby.f90(22,29) ]
      remark #15305: vectorization support: vector length 4
      remark #15309: vectorization support: normalized vectorization overhead 0.
053
      remark #15417: vectorization support: number of FP up converts: single pre
cision to double precision 1   [ C:\users\tim\tim\tim\src\net\bobby.f90(22,19) ]
      remark #15301: OpenMP SIMD LOOP WAS VECTORIZED
      remark #15448: unmasked aligned unit stride loads: 2
      remark #15449: unmasked aligned unit stride stores: 1
      remark #15475: --- begin vector loop cost summary ---
      remark #15476: scalar loop cost: 29
      remark #15477: vector loop cost: 9.500
      remark #15478: estimated potential speedup: 3.050
      remark #15487: type converts: 3
      remark #15488: --- end vector loop cost summary ---
      remark #25456: Number of Array Refs Scalar Replaced In Loop: 2
      remark #25015: Estimate of max trip count of loop=500
   LOOP END

As I said, if you were using gfortran (you didn't say) you might replace the if then else by MERGE, and possibly set -O3 -ffast-math.

0 Kudos
Reply