PGI User Forum
 SearchSearch   MemberlistMemberlist     RegisterRegister   ProfileProfile    Log inLog in 

CUDA-x86.

Tips to improve overall global memory throughtput

 
Post new topic   Reply to topic    PGI User Forum Forum Index -> Programming and Compiling
View previous topic :: View next topic  
Author Message
crip_crop



Joined: 28 Jul 2010
Posts: 68

PostPosted: Tue Jul 31, 2012 7:35 am    Post subject: Tips to improve overall global memory throughtput Reply with quote

Hi there,

I'm really struggling to get any speed-up whatsoever with the code I've been porting. In fact it's actually running twice as slow. I've ran a profile on it and it seems two of the device subroutines are running with an overall global memory throughput of less than 3... pretty bad.

I know that to improve this performance I need to ensure that global memory loads are coalesced and/or shift data to shared memory. However, when I tried the latter this actually reduced performance. With regards to coalescing global memory loads I tried to get all theads to read/write to a local variable and then call syncthreads() at the end of the routine to get all threads to simultaneously write the result to global memory...again, this resulted in a slower execution time.

I'm really running out of ideas now so if anyone has any suggestions or optimizations that worked for them I'd love to hear about them. The code follow, bit long sorry.

Code:
************************************************************************
     
************************************************************************

       attributes(global) subroutine fock2a(iuhf,numthreads,
     & blocksize,natoms,nbasis)
      implicit none
   
      integer :: norbk,norbl,llk,lll,i,ii,j,jj,ij,ijw,k,kk,l,
     &     ll,kd,ld,kld,kw,lw,klw,iim,jjm,iw,ikw,jw,jlw,
     &     thread,iank,ianl,katm,latm,tx,bx,ijw2,check_katm,check_latm

      double precision :: scale,sum,dx,dy,dz,rab
      integer,value :: numthreads,blocksize,iuhf,natoms,nbasis
      integer ij_check,counter,rowno,col,x,y,start,endd,middle,pair,
     &     kloop,lloop,ijkl,work,remaining,istat
      real temp
c$$$      integer, dimension(*),shared:: s_lowlim

  !    double precision, dimension(45,45):: w2_local

      tx=threadIdx%x
      bx=blockIdx%x
      ij=((bx-1)*blocksize)+tx   
       
         if (ij.le.numthreads) then 

            ftot1(ij)=0

         katm=LUT(ij,1)
         latm=LUT(ij,2)

         if (iuhf.eq.2) then
            scale=1.0d0
         else
            scale=0.5d0
         endif
         
         if(katm.eq.latm)then
c     
c     Diatomic vector
c     
            llk=lowlim(katm)
            iank=ian(katm)
            norbk=natorb(iank)

            do latm=katm,natoms

               if(katm.ne.latm) then

!     Find integral index for each atom pair
                  pair=0
                  kloop=0
                  ijkl=0
                  do while (ijkl.eq.0)
                     kloop=kloop+1
                     do lloop=kloop,natoms
                        pair=pair+1
                        if(kloop.eq.katm.and.lloop.eq.latm)ijkl=pair
                     end do
                  end do

                  dx=c(1,latm)-c(1,katm)
                  dy=c(2,latm)-c(2,katm)
                  dz=c(3,latm)-c(3,katm)
                  rab=dsqrt((dx**2)+(dy**2)+(dz**2))
c     
c     Lower basis functions labels
c     
                  lll=lowlim(latm)
c     
c     Atomic numbers
c     
                  ianl=ian(latm)
c     
c     Number of basis functions
c     
                  norbl=natorb(ianl)

c     
c     
c****************************************************************************
c     *                                                                          *
c     *                                                                          *
c     *    Atom k                                                                *
c     *                                                                          *
c     *                                                                          *
c****************************************************************************
c     
c     
                  ijw=0
                  i=0
                  do while (ijw.eq.0)
                     i=i+1
                     ii=llk+i-1
                     do j=1,i
                        jj=llk+j-1
c     
c     address in ftot
c     
                        ij_check=(ii*(ii-1)/2)+jj
c     
c     address ij in w2
c     
                        if(ij_check.eq.ij) ijw=(i*(i-1)/2)+j
c     
                     end do
                  end do

                  sum=0.0d0
c     
                  do k=1,norbl
                     kk=lll+k-1
                     do l=1,norbl
                        ll=lll+l-1
c     
c     address kl in dtot
c     
                        kd=max(kk,ll)
                        ld=min(kk,ll)
                        kld=(kd*(kd-1)/2)+ld
c     
c     address kl in w2
c     
                        kw=max(k,l)
                        lw=min(k,l)
                        klw=(kw*(kw-1)/2)+lw
c     
c     Total Fock Element
c     
                        if(iuhf.eq.2)then
                           sum=sum+(dtot(kld)+dtotb(kld))*
     &                          w2(ijw,klw,ijkl)
                        else
                            sum=sum+dtot(kld)*w2(ijw,klw,ijkl)

                         end if
                     end do
                  end do

                  ftot1(ij)=ftot1(ij)+sum
                     
               end if
               end do

               latm=katm
               lll=llk
               ianl=iank
               norbl=norbk
               
               do katm=1,latm

                  if(katm.ne.latm) then

!     Find integral index for each atom pair
                     pair=0
                     ijkl=0
                     kloop=0
                     do while (ijkl.eq.0)
                        kloop=kloop+1
                        do lloop=kloop,natoms
                           pair=pair+1
                           if(kloop.eq.katm.and.lloop.eq.latm)ijkl=pair
                        end do
                     end do

                     dx=c(1,latm)-c(1,katm)
                     dy=c(2,latm)-c(2,katm)
                     dz=c(3,latm)-c(3,katm)
                     rab=dsqrt((dx**2)+(dy**2)+(dz**2))
c     
c     Lower basis functions labels
c     
                     llk=lowlim(katm)
c     
c     Atomic numbers
c     
                     iank=ian(katm)
c     
c     Number of basis functions
c     
                     norbk=natorb(iank)


c     
c     
c****************************************************************************
c     *                                                                          *
c     *                                                                          *
c     *    Atom l                                                                *
c     *                                                                          *
c     *                                                                          *
c****************************************************************************
c     
c     
                     i=0
                     ijw=0
                     do while(ijw.eq.0)
                        i=i+1
                        ii=lll+i-1
                        do j=1,i
                           jj=lll+j-1
c     
c     address in ftot
c     
                           ij_check=(ii*(ii-1)/2)+jj
c     
c     address ij in w2
c     
                           if (ij_check.eq.ij) ijw=(i*(i-1)/2)+j
c     
                        end do
                     end do

                     sum=0.0
c     

                     do k=1,norbk
                        kk=llk+k-1
                        do l=1,norbk
                           ll=llk+l-1
c     
c     address kl in dtot
c     
                           kd=max(kk,ll)
                           ld=min(kk,ll)
                           kld=(kd*(kd-1)/2)+ld
c     
c     address kl in w2
c     
                           kw=max(k,l)
                           lw=min(k,l)
                           klw=(kw*(kw-1)/2)+lw
c     
c     Total Fock Element
c     
                           if(iuhf.eq.2)then
                              sum=sum+(dtot(kld)+dtotb(kld))*
     &                             w2(klw,ijw,ijkl)
                           else
                              sum=sum+dtot(kld)*w2(klw,ijw,ijkl)                     

                           end if
                        end do
                     end do
         
                     ftot1(ij)=ftot1(ij)+sum
                     
                  end if
                  end do

               else
c     
c     
c****************************************************************************
c     *                                                                          *
c     *                                                                          *
c     *    Atom k - Atom l                                                       *
c     *                                                                          *
c     *                                                                          *
c****************************************************************************
c     
c     
c     
c     Diatomic vector
c     
!     Find integral index for each atom pair
                  pair=0
                  kloop=0
                  ijkl=0
                  do while (ijkl.eq.0)
                     kloop=kloop+1
                     do lloop=kloop,natoms
                        pair=pair+1
                        if(kloop.eq.katm.and.lloop.eq.latm)ijkl=pair
                     end do
                  end do

                  dx=c(1,latm)-c(1,katm)
                  dy=c(2,latm)-c(2,katm)
                  dz=c(3,latm)-c(3,katm)
                  rab=dsqrt((dx**2)+(dy**2)+(dz**2))
c     
c     Lower basis functions labels
c     
                  llk=lowlim(katm)
                  lll=lowlim(latm)
c     
c     Atomic numbers
c     
                  iank=ian(katm)
                  ianl=ian(latm)
c     
c     Number of basis functions
c     
                  norbk=natorb(iank)
                  norbl=natorb(ianl)
           

                  do i=1,norbk
                     ii=llk+i-1
                     do j=1,norbl
                        jj=lll+j-1
c     
c     address ij in ftot
c     

                        iim=max(ii,jj)
                        jjm=min(ii,jj)

                        ij_check=(iim*(iim-1)/2)+jjm
                     
c     
                        if(ij_check.eq.ij)then
                           sum=0.0d0
c     
                           do k=1,norbk
                              kk=llk+k-1
                         
c     
c     address ik in w2
c     
                              iw=max(i,k)
                              kw=min(i,k)
                              ikw=(iw*(iw-1)/2)+kw
c     
                             
                              do l=1,norbl
                                 ll=lll+l-1
c     
c     address kl in dtot
c     
                               
                                 kd=max(kk,ll)
                                 ld=min(kk,ll)
                                 kld=(kd*(kd-1)/2)+ld
c     
c     address jl in w2
c     
                                 jw=max(j,l)
                                 lw=min(j,l)
                                 jlw=(jw*(jw-1)/2)+lw
c     
c     Total Fock Element
c     
                               
                                 sum=sum
     &                                -scale*dtot(kld)*w2(ikw,jlw,ijkl)
                                 
                              end do
                           end do
                           
                     
                           ftot1(ij)=ftot1(ij)+sum
                             
c     
c     
                        end if
                     end do
                  end do


               end if
         
          end if
c     
         
                                 end

************************************************************************
     
************************************************************************
Back to top
View user's profile
mkcolg



Joined: 30 Jun 2004
Posts: 6125
Location: The Portland Group Inc.

PostPosted: Wed Aug 01, 2012 4:02 pm    Post subject: Reply with quote

Hi crip_crop,

I've been think about this one but am not sure. It seems like the problem would be the random non-coalesced memory accesses, but I guess not. Have you profiled the code?

I'll forward this on to some of our other application engineers to see if anyone else has any ideas.

- Mat
Back to top
View user's profile
Michael Wolfe



Joined: 19 Jan 2010
Posts: 42

PostPosted: Wed Aug 01, 2012 4:14 pm    Post subject: Reply with quote

1. You have lots and lots of global memory array accesses that are not going to be coalesced. That may be just an artifact of your application. Look at:
lowlim(katm) where katm=LUT(ij,1)
So katm has different values for each thread, they aren't necessarily adjacent, non-coalesced
natorb(iank), where iank=ian(katm), same thing

c(1,latm) where latm=LUT(ij,2), same thing

w2(ijw,klw,ijkl) where ijw is set to some value in one of the loops above.

Add to this divergence in loops like the do while(ijw.eq.0)

I'm not at all sure that using local memory is the right thing for you, except for local scalars. Local arrays are implemented in the physical global memory, so you have the same problem of accesses to the global memory, and those accesses are not coalesced.

The code is long and has lots of data-dependent branches and many computed array indices; this results in divergence and noncoalesced loads, which unfortunately is not the application space for which GPUs are optimized.
Back to top
View user's profile
crip_crop



Joined: 28 Jul 2010
Posts: 68

PostPosted: Tue Aug 07, 2012 2:20 am    Post subject: Reply with quote

Quote:
I've been think about this one but am not sure. It seems like the problem would be the random non-coalesced memory accesses, but I guess not. Have you profiled the code?


Hi Mat, yes I profiled the code, that's how I know the global memory throughput is so low.

Quote:
The code is long and has lots of data-dependent branches and many computed array indices; this results in divergence and noncoalesced loads, which unfortunately is not the application space for which GPUs are optimized.


The original code is quite different as each thread has it's own katm and latm but I had to redesign the algorithm because of the summation:

Code:
ftot1(ij)=ftot1(ij)+sum


meaning that multiple threads could be writing to the same ij value which gives race condition.

I guess the only way around it would be to just implement this routine on the CPU and pass the data back to the GPU. Hopefully the data transfer overhead won't be too great.

Cheers,
Crip_crop
[/b]
Back to top
View user's profile
Display posts from previous:   
Post new topic   Reply to topic    PGI User Forum Forum Index -> Programming and Compiling All times are GMT - 7 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © phpBB Group