Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.
Announcements
FPGA community forums and blogs on community.intel.com are migrating to the new Altera Community and are read-only. For urgent support needs during this transition, please visit the FPGA Design Resources page or contact an Altera Authorized Distributor.
29285 Discussions

Cycling block-do-construct with inner block-construct

zp3
Beginner
1,973 Views

Hi, I'm wondering if there exists a way (other than branching) for exiting or cycling within a inner block in a do block:

...
do i=1,10
    block
        integer :: k
        ...
        if (...) then
            ...
            cycle !not possible
        end if
        ...
    end block
end do

More general, the question is, if its possible to terminate the execution of a block-construct without using IF/GOTO? I've looked into the standard but I've found no other possibilities...

IMO such a feature would be especially usefull in combination with DO CONCURRENT and the need of iteration local variables.

Thanks

0 Kudos
12 Replies
mecej4
Honored Contributor III
1,973 Views

Is this what you had in mind?

program test
implicit none
integer :: i

DOXYZ: do i=1,10
    block
        integer :: k
        k=-100
        if (mod(i,3).eq.0) then
            k=i*i+1
			write(*,*)'For i = ',i,', k set to ',k,', cycling'
            cycle DOXYZ
        end if
    end block
	write(*,*)'Block ended with i = ',i
end do DOXYZ
end program

If not, and you really want CYCLE and EXIT to apply to just the block and not to the entire loop body, I don't know what the meaning of CYCLE should then be, because the block is not by itself a construct for repetition. Similarly, allowing EXIT to exit the block construct would give that construct a facility that is not provided in the older IF ... THEN ... ELSE...ENDIF construct.

0 Kudos
FortranFan
Honored Contributor III
1,973 Views

Not sure I too understand what exactly you mean by CYCLE an inner block - if you want to cycle, why not make the inner block a DO loop also?

Anyways, note EXIT statement is supported in BLOCK construct per Fortran 2008 standard and if I'm not mistaken (Intel can confirm), this feature will be available in Intel Fortran starting with 16.0 release (you can test it in 16.0 beta).  See a use for it in a branch prediction pattern in message#5 of this thread: https://software.intel.com/en-us/forums/topic/516000.  

0 Kudos
zp3
Beginner
1,973 Views

Thanks for your answer!

Hmm strange...

Okay I've tested your example and it works even without the use of a label. In my particular code I'm using it within a module procedure and for some curious reason the compiler gives me the error message:

error #6604: The construct name in the CYCLE statement does not match any DO construct to which the CYCLE statement belongs.   [DOXYZ]
                    cycle DOXYZ
--------------------------^

without the label:

error #6602: A CYCLE or EXIT statement must not be used with a non-DO block.
                    cycle
--------------------^

Maybe a bug? I'm using ifort 16.0 beta

 

0 Kudos
mecej4
Honored Contributor III
1,973 Views

We would have to see the full context (module source code, complete) to reproduce and understand what the compiler is saying.

My example code has just a single loop, so the label XYZ is not needed. However, if you had two nested DO loops, you might need labels if you wanted the CYCLE inside the BLOCK construct to cycle the outer DO loop rather than the inner DO loop.

0 Kudos
zp3
Beginner
1,973 Views

When I modify your example, so that I would only exit the block and not the loop and change the DO to a DO CONCURRENT:

program test
implicit none
integer :: i

do concurrent (i=1:10)
    block
        integer :: k
        k=-100
        if (mod(i,3).eq.0) then
            k=i*i+1
            write(*,*)'For i = ',i,', k set to ',k,', cycling'
            exit
        end if
    end block
    write(*,*)'Block ended with i = ',i
end do
end program

I get the error message:

error #8432: An EXIT statement shall not belong to a DO CONCURRENT construct.
            exit
------------^

So the exit statement gets associated with the do-construct and not with the block-construct. I'm not sure if a block-construct even understands the exit command. The standard says:

6 2 An EXIT statement belongs to a particular construct. If a construct name appears, the EXIT statement belongs 7 to that construct; otherwise, it belongs to the innermost DO construct in which it appears.

If I name the block:

program test
implicit none
integer :: i

do concurrent (i=1:10)
    DOXYZ: block
        integer :: k
        k=-100
        if (mod(i,3).eq.0) then
            k=i*i+1
            write(*,*)'For i = ',i,', k set to ',k,', cycling'
            exit DOXYZ
        end if
    end block DOXYZ
    write(*,*)'Block ended with i = ',i
end do
end program

I get the error:

error #8490: Transfer of control to the interior of this block from outside the block is prohibited.   [LA]

Buuh, that seems all too strange to me...

0 Kudos
Steven_L_Intel1
Employee
1,973 Views

Both of those from post 6 look like compiler bugs to me. I will escalate them to development. Issue ID is DPD200372670.

0 Kudos
zp3
Beginner
1,973 Views

The first compiler error from post 6 might actually not be a bug: As quoted above, the standard says, that a exit statement gets automatically associated with the innermost loop when a name is omitted, even though the standard also prohibits the use of an exit statement in combination with a do concurrent loop...

0 Kudos
Steven_L_Intel1
Employee
1,973 Views

You're right - I had not noticed that.  This rule needed to be added to prevent changing the meaning of F2003-compliant code.  Thanks.

0 Kudos
jimdempseyatthecove
Honored Contributor III
1,973 Views

Regarding #8

I see nothing inherently wrong with an exit in a DO CONCURRENT because it is the responsibility of the programmer to make sense of what happens due to the discrepancies resulting from the loop actually being performed concurrently (multiple threads), concurrently (multiple vector lanes) or sequentially.

As an approximate equivalent, assume an array of random data, where you use a parallel do to perform a search, or DO CONCURRENT to perform the search. Where any of the concurrencies that can find a match can exit and cause the other concurrencies to exit, with the caveated that the first match temporally found is not necessarily the match returned (race condition), nor is the match returned necessarily the same as that returned had the array been searched sequentially. The programmer assumes the responsibility to sort this out.

Parallel do does not have this capability, neither does do concurrent, but you can start a parallel region, split the array into sections, have each thread search the section using a for loop, and if found a match, inform all threads a match was found (thus causing the additional threads to abort their search). This is not an unusual circumstance, and I see no reason why exit cannot be treated in this way.

This said, there are too many other programmers, not willing to take on the responsibility, and wanting the compiler to say "can't do that". IMHO this this should be a warning, not an error.

Jim Dempsey

0 Kudos
jimdempseyatthecove
Honored Contributor III
1,973 Views

I forgot to add an additional 2 cents

Inside the DO CONCURRENT and inside the PARALLE DO it is perfectly acceptable to have a STOP statement, which essentially forces all concurrencies to exit, not only the loop but the process as well.

Jim Dempsey

0 Kudos
Steven_L_Intel1
Employee
1,973 Views

The bug will be fixed in 16.0 Update 1.

0 Kudos
zp3
Beginner
1,973 Views

Thanks!

0 Kudos
Reply