ISO/IEC JTC1/SC22/WG5 N2178 WG5 letter ballot 1 on Fortran 2018 interpretations Steve Lionel, October 24, 2020 This is the first set of draft interpretations for Fortran 2018. They have all been approved in a J3 letter ballot. The WG5 ballot opened September 24, 2020 and closed October 24, 2020. Eleven votes were received by the close of balloting. Interpretation F18/015 failed this letter ballot with eight "No" votes and two comments. All other interpretations passed (F18/011 had one comment that was not related to the technical content of the interpretation.) Key for the Result line: Y vote passes unconditionally. C vote passes, subject to minor changes noted below N vote fails. Returned to J3 for further work. F18/ F18/ F18/ F18/ F18/ F18/ F18/ F18/ F18/ F18/ F18/ 001 002 003 004 005 006 008 009 010 011 012 Chen Y Y Y Y Y Y Y Y Y Y Y Clune Y Y Y Y Y Y Y Y Y Y Y Cohen Y Y Y Y Y Y Y Y Y Y Y Corbett Y Y Y Y Y Y Y Y Y Y Y Friesen Y Y Y Y Y Y Y Y Y Y Y Lionel Y Y Y Y Y Y Y Y Y Y Y Long Y Y Y Y Y Y Y Y Y C Y Reid Y Y Y Y Y Y Y Y Y Y Y Shterenlikht Y Y Y Y Y Y Y Y Y Y Y Snyder Y Y Y Y Y Y Y Y Y Y Y Steidel Y Y Y Y Y Y Y Y Y Y Y Result Y Y Y Y Y Y Y Y Y Y Y F18/ F18/ F18/ F18/ F18/ F18/ 013 014 015 016 017 018 Chen Y Y N Y Y Y Clune Y Y N Y Y Y Cohen Y Y N Y Y Y Corbett Y Y N Y Y Y Friesen Y Y N Y Y Y Lionel Y Y C Y Y Y Long Y Y N Y Y Y Reid Y Y N Y Y Y Shterenlikht Y Y C Y Y Y Snyder Y Y Y Y Y Y Steidel Y Y N Y Y Y Result Y Y N Y Y Y Status Number Title Pass F18/001 ACOSH principal value specification is wrong Pass F18/002 Internal procedures in generic interface blocks Pass F18/003 Pointer association of component of non-definable selector Pass F18/004 Program execution sequence with failed images Pass F18/005 Does INPUT_UNIT really identify the same unit as *? Pass F18/006 Connection of INPUT_UNIT on different images Pass F18/008 Contradictory assumed-rank requirements Pass F18/009 Bad examples in IEEE_ARITHMETIC functions Pass F18/010 Categories of pure procedures Pass F18/011 Categories of elemental procedures Pass F18/012 Internal procedure in a generic interface Pass F18/013 TEAM_NUMBER arguments and intrinsic function are ambiguous Pass F18/014 Type of OPERATION arguments to the REDUCE intrinsic FAIL F18/015 Example in C.6.8 is wrong Pass F18/016 Host association changes in Fortran 2018 Pass F18/017 Final subroutine invocation order Pass F18/018 Public namelist and private variable Comments on F18/011 Bill Long --------- F08/011: The last paragraph of the answer proposes additional improvements in F202X. Have these been done? (I do not have objections to the general answers to the interp or the proposed edits to F18.) Comments on F18/013 John Reid --------- Edit for [20:30] 3.145.4 team number, definition. The edit and its expanded version are not consistent. I suggest removing "(5.3.4)" from the expanded version. I think that this reference is unnecessary with the term "sibling teams" defined (see edit for [20:27+] Terms and definitions). Comments on F18/015 Anton Shterenlikht ------------------ I have 2 comments on this example code. Comment 1 --------- 21 ! Keep 1% spare images if we have a lot, just 1 if 10-199 images, 22 ! 0 if <10. 23 images_spare = MAX(NUM_IMAGES()/100,0,MIN(NUM_IMAGES()-10,1)) There are 2 problems with this comment and with this code: 1. If NUM_IMAGES() returns 10, images_spare will be 0, not 1. Only when NUM_IMAGES() is 11, will images_spare becomes 1. Either the comment must be changed, or the code should be changed to "MIN(NUM_IMAGES()-9,1)". 2. The use of ",0" in the middle of the expression does not achieve anything, and is only confusing. The output of NUM_IMAGES() is non-negative, hence NUM_IMAGES()/100 is non-negative, so the result of the expression is unchanged if that ",0" is removed: images_spare = MAX( NUM_IMAGES()/100, MIN(NUM_IMAGES()-10,1) ) I prefer to rewrite this line explicitly as: images_spare = 0 if ( NUM_IMAGES() .GE. 10 ) images_spare = 1 if ( NUM_IMAGES() .GE. 200 ) images_spare = NUM_IMAGES()/100 The example is very complex already - no need to overcomplicate it further. Comment 2 --------- Variable name "team_number" is a poor choice because we have intrinsic function TEAM_NUMBER. It would be more clear to use this intrinsic in line 88, i.e. replace 88 IF (team_number == 1) THEN to 88 IF ( TEAM_NUMBER() == 1) THEN and give the variable a different name, e.g. "tnum" or "team_num". Steve Lionel ------------ While I generally agree with Anton's remarks on 015, I find the suggested replacement for the calculation of images_spare with three statements to be unwieldy. He is correct that if NUM_IMAGES() is 10 then there are zero spare images, not one as the comment suggests, but this is easily fixed. (I also agree that the ,0 is unnecessary). My suggested replacement is: images_spare = MAX(NUM_IMAGES()/100,MIN(NUM_IMAGES()-9,1)) I tested this in the range 1:201 and it delivered the desired result. Malcolm Cohen ------------- NO vote for F18/015: Individually these don’t really warrant a “no”, but together I think they do. (1) The formula given in the comment differs from the code for the number of “spare” images. (a) The comment should be changed to ! Choose how many images to keep as spares. (b) The code should be changed, either to something very simple like images_spare = (NUM_IMAGES()+90)/100 or to the several lines suggested by Anton. My preference would be for something really simple, but anything reasonable that resolves the comment/=code dichotomy is fine. (2) The variable “team_number” should be changed to “team_num”, or anything else that is understandable but not the name of a standard intrinsic. (3) The error handling is half-hearted. It should be improved by (a) following “IF (status == STAT_FAILED_IMAGE) EXIT simulation” (after CHANGE TEAM) with IF (status/=0) EXIT outer (b) following “END TEAM (STAT=status) simulation” with IF (status/=0 .AND. status/=STAT_FAILED_IMAGE) EXIT outer (c) following “SYNC ALL (STAT=status)” (two lines down from (b)) with IF (status/=0 .AND. status/=STAT_FAILED_IMAGE) EXIT outer Jon Steidel ----------- F08/015: The example still has flaws, which the HPC subgroup is actively working on. We should complete this work before passing the interpretation and applying edits that are not correct. Robert Corbett -------------- F18/015 N The proposed replacement example is pointlessly complicated. Brian Friesen ------------- Regarding F18/015: This example needs further edits to correct some errors. Daniel Chen ----------- F18/015: I agree with Other people's analysis that this example needs to be corrected. Bill Long --------- F08/015: Still room for improvement. People have already started working on this, and we should allow that process to complete before passing changes in this example. John Reid --------- Reason for no vote on F18/015. Nathan Weeks has pointed out to me that there are three problems with the new code for C.6.8 in N2176, viz 1. The code for choosing the number of spares does not correspond to the comment for it. The simplest solution is to change "10" to "9" in the line images_spare = MAX(NUM_IMAGES()/100,0,MIN(NUM_IMAGES()-10,1)) but I prefer the suggestion of Anton Shterenlikht to replace this line by images_spare = 0 if ( NUM_IMAGES() .GE. 10 ) images_spare = 1 if ( NUM_IMAGES() .GE. 200 ) images_spare = NUM_IMAGES()/100 It is absolutely clear what this does, which I see as an example of good practice. It does not need a comment to explain what is going on. Therefore I suggest changing the comment to ! Choose how many images to keep as spares. 2. The variable images_used is incremented only on image 1 but is referenced by other images near the beginning and end of DO outer. The statement IF (THIS_IMAGE () images_used) done = done[1] near the end of DO outer may be replaced by IF (team_number == 2) done = done[1] which avoids the problem here and I think it is an improvement anyway. A simple solution for the use of images_used near the beginning of DO outer in the statement team_number = MERGE (1, 2, local_index<=images_used) is to make images_used a coarray and replace "images_used" by "images_used[1]" in this statement. This will need the addition of a SYNC ALL statement just before the statement outer : DO to ensure that the correct value is used on all images on the first iteration of the loop. 3. The intention is that on each cycle of the DO iter loop, a calculation is performed on the worker images and if any of them fail during this, the calculation is resumed from a checkpoint with the failed images replaced by spares. On resumption, the variable read_checkpoint should have the value true on all the worker images so that they access the checkpoint data. On a replacement image, this variable will still have its initial value of false. A simple way to fix this is to change the initial value of read_checkpoint to true. The subroutine simulation_procedure will need to keep track of which checkpoint data to use or that none is available because this is an initial call. The statement read_checkpoint = .FALSE. ! Initial startup, not from checkpoint. should be replaced by the statement read_checkpoint = .TRUE. This ensures that read_checkpoint has the value true on a spare image when it first comes into use. For clarity I also suggest changing the declaration of read_checkpoint to LOGICAL :: read_checkpoint ! If read_checkpoint true on entering ! simulation_procedure, go back to previous check point if one ! exists.