ARSC T3E Users' Newsletter 192, March 31, 2000

UAF Science Potpourri: Saturday April 1st

No fooling - this year's Science Potpourri will take place on Saturday, April 1st, from noon to 5 PM in the Natural Sciences Facility on the UAF Campus.

The ARSC visualization and access lab in Room 161 will be open and staff will be on hand to explain supercomputing and run demos. The Science Potpourri will feature lots of other hands-on science-related activities and shows for kids of all ages, from three to ninety three. All events are free. The Science Potpourri is the annual open house of the College of Science, Engineering, and Mathematics of the University of Alaska Fairbanks.

Safer File Assignments

The article, "File Assignment: Dangerous but Useful," appeared in issue #125 . The title said it all.

The danger in using assign arises because, by default, assignments are stored in a shared file ($TMPDIR/.assign) whether they're made by NQS scripts, interactive assign commands, or hardwired Fortran calls to ASNFILE , ASNUNIT , or ASSIGN .

If you're not careful, assignments made for one job will cross sessions, affect unrelated programs, and persist for months. Ugh!

The latest ARSC user to get into trouble was on the J90. He was running the same program simultaneously in two different NQS jobs and had included assign commands like these in the qsub scripts:


  ...
  # in script 1
  assign -a job_1.output u:11     
  ...

  ...
  # in script 2
  assign -a job_2.output u:11     
  ...
His goal was to create two separate files, but due to the global nature of assignments, the output of both jobs went to the same file, corrupting it.

A solution is to abandon the default method and instead, store assignments to environment variables. Their scope is limited to the current process, so they're less likely to have unintended consequences. Here's the basic idea, from "man assign":


   The location of the active assign environment can be changed by
   assigning a file name or a process environment variable to the
   FILENV environment variable.
Storing assignments to environment variables requires two changes:
  1. Define the environment variable, FILENV . Assign it the name of a second environment variable, which is the place assign will store assignments.

    For example:

    
         # korn shell users:
         export FILENV=\$TMP_ASSIGNS    
    
         # C shell users:
         setenv FILENV \$TMP_ASSIGNS    
    
    Notes:
    1. "TMP_ASSIGNS" is an arbitrary name, hopefully unique. In "man assign", example 4, they use "EVAR". Your choice.
    2. The backslash-dollar sign, "\$", is required.
  2. Once you've defined FILENV , as in step 1, assign notices, and behaves differently. Instead of writing assignments to a ".assign" file, it writes a command to STDOUT, which you must eval . "Eval'ing" this command makes the desired assignments take affect.

    For example:

    
         # korn shell users:
         eval $(assign -a job_1.output u:11)
    
         # C shell users:
         eval `assign -a job_1.output u:11`
    

    Notes:

    1. The eval IS REQUIRED!
    2. The eval IS REQUIRED!
    3. The eval IS REQUIRED!
    4. C shell users: Those are backticks, not single quotes.
    5. Korn shell users may actually use either syntax, above.

    EXAMPLES:

    Batch NQS Job Example: Here's a sample NQS script. The assignment affects the run of "./tstname", but is limited in scope to the particular NQS job and evaporates when the job ends:

    
        #QSUB -q mpp
    
        cd /u1/uaf/baring/Prj/Assign
    
        # Store assign info to environment variable, TMP_ASSIGNS
        export FILENV=\$TMP_ASSIGNS           
    
        # Make an assignment
        eval $(assign -a testAssignedFile.out u:41)
    
        # Run program which needs the above assignment
        ./tstname
    
    Interactive Session Example: Here's a test program:
    
          program tstname
          implicit none
    
          real    x
          integer j, IER
    
          open (unit=41, form="FORMATTED", status="UNKNOWN")
    
          do j=1,10
            x = real(j)/100.
            write (41, '(f8.4)') x
          enddo
    
          print*, "Unit 41 written successfully."
          close (unit=41)
          end
    
    In the following commands, the file name, "testAssignedFile.out" is assigned to unit 41. (The command, assign -V prints all current assignments.)
    
        YUKON$ export FILENV=\$TMP_ASSIGNS
        YUKON$ eval $(assign -a testAssignedFile.out u:41)
        YUKON$ assign -V
          # ASSIGN ENVIRONMENT VARIABLE=$TMP_ASSIGNS
          assign -a testAssignedFile.out u:41
        YUKON$ ./tstname
          Unit 41 written successfully.
        YUKON$ ls -l testAssignedFile.out
          -rw-------   1 baring   staff   90 Mar 29 15:41 testAssignedFile.out
     
    
    Now, if I open a second telnet session and list assignments, I see this:
    
        YUKON$ assign -V
          # ASSIGN ENVIRONMENT FILE=/tmp/baring/.assign
    
    This is the desired effect. The assignment in the first session has no affect on the second session.

    If I switch back to the first window, I can clear the assignment with assign -R , but I must use eval again:

    
        YUKON$ eval $(assign -R)
        YUKON$ assign -V
          # ASSIGN ENVIRONMENT VARIABLE=$SESSION_ASSIGN
    
    Alternatively, since the variables FILENV and SESSION_ASSIGN only exist in this session, logging out will zap them.

    Computation Steering: A First Look

    Users often wish they could communicate with a running program.

    This process, often know as computational steering, is typically most useful in long iterative computations, when, for example, there is some report you'd like more or less of, to change a control parameter, or simply come to graceful conclusion saving the work so far. Another important use is when debugging or analyzing code, as it is often better that running under the debugger, as performance is preserved. The technique, however, does require the main loop of the program be modified.

    The code below illustrates a somewhat primitive but portable way to communicate with your program while it is running. The key features are as follows.

    • In this example, a primitive iterative computation is undertaken with the number of iterations and the printout frequency fixed by the code and data dumped only at the end.
    • The variable 'islook' determines how many iterations there are between checks for a steering instruction.
    • Every 'islook' iterations, the code tests if the file 'read_steering_control' exists and, if it does, reads the file, 'steering_control'.

      The value in 'steering_control' is used as the new value for 'ipiter'. Using 'read_steering_control' as a flag lets the user edit 'steering_control' leisurely and then create (touch) 'read_steering_control' when they want the steering actions undertaken.

      Once the code reads the steering instructions, 'read_steering_control' is deleted and the user can change 'steering_control' again, if they wish.

    • To be safe, both err and end keywords are used in the open and close statements to ensure safe behavior if the files are not in a suitable status when the code reads them. This is to prevent the job failing when steering is performed. The worst that can happen is that the change doesn't take effect.
    • Both files are closed. Note that 'read_steering_control' is also deleted. This prevents repeated reads of the steering file and indicates to the user that the steering file has been processed.

In this primitive example only one variable is modified, but it would be a simple exercise to expand the contents of 'steering_control' to permit an emergency dump, change 'ip1' or 'ip2', or alter 'frac'.


      program steer1
      implicit none

! problem size
      integer isize
      parameter (isize=1024*1024)
      real a(isize)
! compute loop limits
      integer i

! number of iterations
      integer iter,niter

! interest points
      integer ip1,ip2

! action control variable
      integer ido
      integer ipiter
      real frac

! steering variables
      integer islook,ipnew

! basic iteration count
      niter=10000
! print every ipiter iteration
      ipiter=100


! simple smoothing parameter
      frac=0.99


!! steering control
      islook=100

! boundary conditions
      a(1)=-1.0
      a(isize)=1.0
      do i=2,isize-1
        a(i)=0.0
      enddo


! print interest points
      ip1=100
      ip2=10000

      do iter=1,niter
        do i=2,isize-1
          a(i)=a(i)+frac*(a(i+1)+a(i-1)-2*a(i))
        enddo

        if(mod(iter,ipiter).eq.0) then
          write(6,*) ' iteration ',iter,' data ',a(ip1),a(ip2)
        endif


!! look for steering input
        if(mod(iter,islook).eq.0) then
          open(61,file='read_steering_control',
     !           status='old',
     !           err=6101)
          open(60,file='steering_control',
     !           status='old',
     !           err=6100)
          read(60,9000,err=6000,end=6000) ipnew
 9000     format(i6)
          write(6,*) ' direction is ',ipnew
          if(ipnew.gt.0) then
            ipiter=ipnew
          endif
 6000     continue
          close(60,err=6001)
 6001     continue
 6100     continue
          close(61,err=6101,status='delete')
 6101     continue

        endif
      enddo

      write(10) a

      stop
      end

GNU Fortran 95

As posted to comp.lang.fortran, the project to bring about GNU Fortran 95 has started. The official announcement is on the GCC home page:

http://gcc.gnu.org

which refers to its home page:

http://xena.eas.asu.edu/~andyfor details.

Quick-Tip Q & A



A:{{  I'm in four Unix permission groups:
  {{
  {{    yukon$ groups 
  {{    hyprfast bigfoot wulfdown marsbar
  {{
  {{  Whenever I create a new file, it's in "hyprfast," but I've left
  {{  those guys behind.  So I'm always running, or forgetting to run,
  {{  chgrp:
  {{
  {{    yukon$ chgrp wulfdown new.file.out
  {{
  {{  How can I change my default group to "wulfdown"?



  Confusion reigns in this question.

  In UNICOS (but not every Unix), a new file is put in the group of the
  directory in which it is created.

  Changing your primary group to "wulfdown," which you can't do
  yourself, anyway, wouldn't help.  You need to "chgrp" manually, as
  shown above, or change the group of the directory (or entire
  subtree).   If you do all your "WULFDOWN" work in certain
  directories, this might make sense.




Q: Gol' Dern it an Dang Blast It All!

   I opened an old file, "my_stuff.original", with vi, like this:
 
     vi my_stuff.original
 
   Then, before making ANY changes, realized I shouldn't mess with the
   original, but should create and edit a new version.  So I used vi to
   re-save it as a new file:

     :w my_stuff.unoriginal

   Then I typed in some limericks, etc., saved and quit:

     :wq

   But vi pulled a switch-er-roo.  "my_stuff.original" now contains the
   NEW version, and "my_stuff.unoriginal" contains the original
   version. This is the opposite of what I wanted!

   What happened?  And, if ":w" isn't right, how can I change the name
   of the file I'm editing?

[ Answers, questions, and tips graciously accepted. ]


Current Editors:
Ed Kornkven ARSC HPC Specialist ph: 907-450-8669
Kate Hedstrom ARSC Oceanographic Specialist ph: 907-450-8678
Arctic Region Supercomputing Center
University of Alaska Fairbanks
PO Box 756020
Fairbanks AK 99775-6020
E-mail Subscriptions: Archives:
    Back issues of the ASCII e-mail edition of the ARSC T3D/T3E/HPC Users' Newsletter are available by request. Please contact the editors.
Back to Top