do concurrent in parallel? speed-up?

Tim Prince n8tm@aol.com
Tue Feb 11 23:22:00 GMT 2014


On 2/11/2014 2:31 PM, Damian Rouson wrote:
> On Tue, 11 Feb 2014 13:15:34 -0500, Tim Prince wrote:
>
>> I've turned my masked do concurrents into DO loops with MERGE for the benefit of gfortran 4.9. ifort
>> needs VECTOR ALIGNED directives to get full performance of masked DO CONCURRENT, and it's still fully
>> effective only for single thread vectorization.
> Could you provide a simple example and give rough estimates of the resulting speedup with gfortran 4.9 and the CPU employed?
>
> Damian
#if defined __INTEL_COMPILER
!dir$ vector aligned
           do concurrent( i= 1:n, a(i) > b(i))
             a(i)= a(i)-b(i)*d(i)
             c(i)= a(i)+c(i)
           enddo
#else
           do i= 1,n
             temp= a(i) > b(i)
             a(i)= a(i)-merge(b(i)*d(i),0.,temp)
             c(i)= merge(a(i),0.,temp)+c(i)
           enddo
#endif
That one doesn't vectorize with gfortran. Even without vectorization, 
the change from do concurrent to merge improves performane by about 30% 
on several CPU generations. It can be vectorized by gfortran for avx by 
splitting into individual do loops, but this involves an additional 
temporary array, so the vectorization would not do much more than double 
performance, in the absence of loop re-fusion.  Intel Cilk(tm) Plus can 
achieve excellent performance by that route, but it's very picky about 
alignment assertions.  As Tobias mentioned, the alignment assertions for 
avx must match data declarations or compiler data alignment 
specification (-align array32byte).
The merges accomplish about what ifort does in optimizing the mask 
operation by minimizing the required operations.  It prevents use of 
fused multiply-add; tests show that appears to be the right choice.
#if defined __INTEL_COMPILER
!dir$ vector aligned
           do concurrent( i= 1:n, e(i) >= t)
             a(i)= a(i)+c(i)*d(i)
             b(i)= b(i)+c(i)*c(i)
             enddo
#else
           do i= 1,n
             a(i)= a(i)+merge(c(i)*d(i),0.,e(i) >= t)
             enddo
           do i= 1,n
             b(i)= b(i)+merge(c(i)*c(i),0.,e(i) >= t)
             enddo
#endif
This one gets 85% of potential performance on my avx2 laptop for 
n==1000.  When built for original corei7, it doesn't vectorize, and the 
loop split costs some performance then too (repeated common operations).

Both examples are from the classic Levine, Callahan, Dongarra netlib 
vector benchmark (if you want to see the f66 code).

-- 
Tim Prince



More information about the Fortran mailing list