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

Variables in DO CONCURRENT Loop Flagged as Unused

SunMesa
Beginner
713 Views

After struggling at length with the FORALL construct, but eventually applying it with some level of comfort, it (of course) became deprecated.

Consequently, I have code for which I'm trying to replace FORALL constructs with DO CONCURRENT equivalents.

The following is a simplified equivalent of a more complex code, and I understand that DO CONCURRENT is not required for the intended result in this example, but it reproduces the compiler response that is giving me concern:

      Program Test_Do_Concurrent
      IMPLICIT NONE
      Integer, Parameter :: NSpans=3,NBins=5
      Integer :: ia,ib,ispan
      Real :: DataSpan(2,NSpans),BinEdge(0:NBins,NSpans),BinWidth(NSpans)
      Data DataSpan /0.,10.,  0.,100.,  0.,1000./
      BinWidth = (DataSpan(2,:)-Dataspan(1,:))/NBins
      Do Concurrent (ib=0:NBins, ia=1:NSpans)
        BinEdge(ib,ia) = DataSpan(1,ia) + ib*BinWidth(ia)
      EndDo
      Do ispan=1,NSpans
        Write(*,'(*(f0.0,2X))')BinEdge(:,ispan)
      EndDo
      End Program Test_Do_Concurrent

Curiously, although this compiles with no errors, the compiler flags the integers ia and ib as unused variables! But the code executes exactly as expected, which clearly indicates that ia and ib are used.

It gets weirder yet: the above was built in Visual Studio 2017, using Intel Parallel Studio XE 19.1.3.311, with the project configured as 64-bit. If I change the project configuration to x86 (32-bit), now the compiler recognizes ia and ib as used variables!

I gather from the Intel documentation of DO CONCURRENT (which I must confess did not significantly advance my understanding) that variables and functions in a DO CONCURRENT block are under very onerous restrictions, but it's not at all clear how that would cause them to become 'invisible' to the compiler, and moreover only in the 64-bit configuration.

I can only speculate that this has something to do with 'locality', another recent Fortran obfuscation that has me similarly baffled. Indeed, if I modify the Do Concurrent command to be:

Do Concurrent (ib=0:NBins, ia=1:NSpans) Shared(ia,ib)

as well as specify /Qparallel in the command line (after the compiler informed me that 'Shared' would be ignored unless I did so), then ia and ib are recognized as being used, in both 32-bit and 64-bit configurations.

Is there a straightforward (or arcane, if necessary) explanation for this behavior? Thanks for any info!

Labels (2)
0 Kudos
6 Replies
Steve_Lionel
Honored Contributor III
700 Views

ib and ia here are "construct entities", existing only within the DO CONCURRENT, but I agree that the compiler should not consider them unused. My guess is that it is a case that was overlooked - as the compiler goes along, it marks variables in its symbol table as used, and the construct entities are not the same ia and ib as outside the DO CONCURRENT, but the warning is still wrong.

0 Kudos
SunMesa
Beginner
697 Views

Hello Steve, thanks for your reply-

That makes sense, but the construct entities ia and ib in the DO CONCURRENT loop are apparently not completely autonomous from those defined outside the loop, because if I remove the declaration of ia and ib as integers in the main program, the compiler considers it a flat-out error for both ia and ib (#6404: This name does not have a type, and must have an explicit type), and points directly at the line executing the DO CONCURRENT. And the inconsistency in the compiler's response depending on 32-bit vs 64-bit configuration remains baffling.

0 Kudos
Steve_Lionel
Honored Contributor III
683 Views

No, that is correct behavior. If you use implicit none, all variables, including construct entities, must be typed. It takes its type from what was declared in the outer scope, but the variable itself is independent. You can demonstrate this by assigning something to ia outside the DO CONCURRENT and then looking at its value after.

0 Kudos
SunMesa
Beginner
662 Views

I did as you suggested, and compiled/ran the following modification of the above test code:

      Program Test_Do_Concurrent
      IMPLICIT NONE
      Integer, Parameter :: NSpans=3,NBins=5
      Integer :: ia,ib,ispan
      Real :: DataSpan(2,NSpans),BinEdge(0:NBins,NSpans),BinWidth(NSpans)
      Data DataSpan /0.,10.,  0.,100.,  0.,1000./
      ia = 55
      ib = 66
      Write(*,*)ia,ib
      BinWidth = (DataSpan(2,:)-Dataspan(1,:))/NBins
      Do Concurrent (ib=0:NBins, ia=1:NSpans)
        BinEdge(ib,ia) = DataSpan(1,ia) + ib*BinWidth(ia)
      EndDo
      Do ispan=1,NSpans
        Write(*,'(*(f0.0,2X))')BinEdge(:,ispan)
      EndDo
      Write(*,*)ia,ib
      End Program Test_Do_Concurrent

and the output is:

55 66
0. 2. 4. 6. 8. 10.
0. 20. 40. 60. 80. 100.
0. 200. 400. 600. 800. 1000.
55 66

indicating that the assignments to ia and ib in the outer scope were unchanged by the activity in the DO CONCURRENT loop.

Running the above in the VS debugger shows that, just before execution of the DO CONCURRENT, there are two independent pairs of variables named ia and ib, both assigned the values 55 and 66 respectively. While subsequently marching through the internals of the DO CONCURRENT loop, neither of these pairs of ia, ib variables ever change their value.

I don't expect I'll ever fully understand the nuances of DO CONCURRENT, but it would be nice to know that I can ignore the unused variable warning in this context.

0 Kudos
Barbara_P_Intel
Moderator
572 Views

I compiled both examples with the current compiler, 2021.8.0. It was released as part of oneAPI HPC Toolkit 2023.1. 

I don't get any warning messages.

$ ifort --version
ifort (IFORT) 2021.8.0 20221119
Copyright (C) 1985-2022 Intel Corporation.  All rights reserved.
$ ifort -qopenmp concurrent1.f90
$ a.out
0.  2.  4.  6.  8.  10.
0.  20.  40.  60.  80.  100.
0.  200.  400.  600.  800.  1000.
$ ifort -qopenmp concurrent.f90
$ a.out
          55          66
0.  2.  4.  6.  8.  10.
0.  20.  40.  60.  80.  100.
0.  200.  400.  600.  800.  1000.
          55          66

No warnings without -qopenmp either.

$ ifort concurrent1.f90
$ ifort concurrent.f90
0 Kudos
Steve_Lionel
Honored Contributor III
564 Views

I was going to gently chide @Barbara_P_Intel  for not adding -warn, since unused variable warnings are not the default, but even when I add that I don't get any complaints from the current compiler.

Reply