POSIX tutorial

POSIX tutorial

Today I'm looking into the POSIX routines, hoping to get multi-processor efficiency.  I have the standard documentation for all the library and function calls, but for a beginner I still have a zillion questions.  Can anyone point me to a good tutorial on the subject?  I'd hate to pester experts with dumb (to them) questions.

DD

27 posts / 0 new
Last post
For more complete information about compiler optimizations, see our Optimization Notice.

Are you referring to the POSIX thread routines? I'm not aware of a tutorial on those. Use of OpenMP is more popular, or you could try using the compiler's autoparallel feature.

Steve - Intel Developer Support

Steve:

I already use OpenMP, and for some tasks it's great.  But now I'm working on a feature that really requires multiprocesses, not multithreads.  I found the list of POSIX Library Procedures, and it has lots of features.  But, for example, how do I arrange for separate processes to share a block of memory -- for updating data that each should know about?  A tutorial would be very helpful here.  Can you point me to one?

DD

You might want to look at MPI (Message Passing Interface). Intel has a version of MPI (http://software.intel.com/en-us/intel-mpi-library) and there are other open source versions of MPI (start with http://www.open-mpi.org/)

Jim Dempsey

www.quickthreadprogramming.com

Well, that's a step forward -- but it seems like overkill.  I only need to read and change the values in an array of 10 real numbers.  That may be possible using PXFSTRUCTCREATE....  Is there a more direct way you can recommend?

DD

Now I'm in real trouble.  I cannot get PXFPIPE, PXFFORK, or PXFWAIT to link.  Here are my declarations:

    USE IFPOSIX
...

    INTEGER(4) IPID,ISTAT,IERROR,IPID_RET,ISTAT_RET,IREADFD,IWRITEFD,JHANDLE

        CALL PXFPIPE(IREADFD,IWRITEFD,IERROR)    ! CREATE PIPE FOR SENDING DATA

        CALL PXFFORK(IPID,IERROR)        ! FORK NEW PROCESS HERE
            CALL PXFWAIT(ISTAT,IPID_RET,IERROR)

Error    11    error LNK2019: unresolved external symbol _PXFPIPE@12 referenced in function _DSEARCH    C:\SYNOPSYSV14\SYNOPSYS200_lib_.lib(Automf.obj)    SYNOPSYS200
Error    12    error LNK2019: unresolved external symbol _PXFFORK@8 referenced in function _DSEARCH    C:\SYNOPSYSV14\SYNOPSYS200_lib_.lib(Automf.obj)    SYNOPSYS200
Error    13    error LNK2019: unresolved external symbol _PXFWAIT@12 referenced in function _DSEARCH    C:\SYNOPSYSV14\SYNOPSYS200_lib_.lib(Automf.obj)    SYNOPSYS200

What's going on?

DD

Do you have the CVF calling mechanism option set? Turn it off.

Steve - Intel Developer Support

Yes.  I have /iface:cvf turned on.  Have to, or nothing works.  This is a huge project ported from CVF.  Is there any way to rewrite the calls so they work in my case?

DD

Oh, I see. The routines you want to use aren't supported on Windows. Sorry.

 I see the documentation doesn't mention that they are Linux/OS X only. I will ask that this be corrected.

You could use Windows API threads.

Steve - Intel Developer Support

There is a Posix Pthreads library available for use with MSVC/Intel-C, but it has, obviously, a CDECL interface. DD will have to weigh the costs of writing interfaces to these for use from Fortran. If any callback functions are going to be passed to the Posix routines, they will have to be CDECL as well.

Pthreads Library for MSVC

Ugggh... this doesn't look good.  Thanks, everyone, for clearing up the fog.  I'll study the API approach.  Grrrr.

DD

Do you really wish to develop, in the year 2013, code tied to STDCALL conventions? Have you noted that if, down the road, you wish to move to x64 code, you will have to redo much of what you are now doing?

Writing to the Pthreads API will give you better portability to Linux. Writing to the Windows threads API will let you target 32- or 64-bit Windows only, but may give you slightly better performance than with Pthreads.

The documentation does indicate that PXFFORK and PXFWAIT are supported on Linux and OS X only. But PXFPIPE is not so noted. I also found PXFLINK and PXFSIGACTION missing this notation. I have found some other errors in the POSIX routine documenattion and have notified our writers.

Steve - Intel Developer Support

Quote:

mecej4 wrote:

Do you really wish to develop, in the year 2013, code tied to STDCALL conventions? Have you noted that if, down the road, you wish to move to x64 code, you will have to redo much of what you are now doing?

Writing to the Pthreads API will give you better portability to Linux. Writing to the Windows threads API will let you target 32- or 64-bit Windows only, but may give you slightly better performance than with Pthreads.

Thank you for your cogent question, mecej4 -- and if I were starting today I would certainly use modern tools and protocols.  But what would you do if you were maintaining and developing a huge code that started in 1962, first on vacuum tubes, and over the years migrated to Honeywell mainframes, IBM minicomputers, CDC mainframes, Unix, DOS, and then Windows about 15 years ago?  Would you re-write thousands of subroutines, weeding out all the legacy code and obsolete calling conventions?  The program works as it is now, and any major overhaul would take months of effort and would introduce countless new bugs.  It ain't broke, so I don't want to fix it.

But I do want to enhance the speed by a factor of 2 to 10, and this requires farming out a group of very time-consuming calculations to separate processes.  Logically it would be quite simple.  But Windows apparently does not support the fork() feature found on Unix.  I was hoping there was an efficient way to do just that.  Looks like there isn't.  Oh, well.  Thank you for the comment, anyway.

DD

Today I have interesting results.  Since there is no fork() option on Win32, I  tried the spawnl() function in C++ instead, called by a Fortran routine.  It works, the new process starts, and I send a command argument that tells the new process to look in a named file for all of the initializations that it needs in order to start up where the parent process did the spawn.  It's not all that much work, and it runs just fine.  Most of the time.

And there's the rub.  The processes call many subroutines, some of which read and write disk files, and if it ever happens that two processes want the same access at the same time, I either get a crash or incorrect data.  So .... Is there any way you can think of whereby I can tell a process to wait for a few milliseconds because a different process is accessing a resource?  Since there is no PIPE in my emulation, it's hard to implement inter-process communication.

Any ideas?

DD

You probably need to add mutexes to synchronize access to the files. Windows treatment of shared ordinary files isn't all that good. You may also want to consider the use of a shared global variable in a DLL - see the sample DLL_Shared_Data for ideas.

Steve - Intel Developer Support

Quote:

DonDilworth wrote:
Is there any way you can think of whereby I can tell a process to wait for a few milliseconds...
There are various "sleep.." functions available, but I doubt that you should think in terms of time rather than a sequence of events that should occur. You can use mutexes, semaphores, etc., as Steve already suggested. Another way, which is simpler,  if it can be used  in your application, is to have the main thread make all decisions as to when to read or write files and calling other threads.

Remember, these are not threads, they are different processes.  So the tools are different.

Here's an idea I am trying now:  Subroutine A wants to open and read from file 23.  Subroutine B may have that open at the moment.  So in A, I have

10      CLOSE (23,ERR=10)

        OPEN (23)

        (Use this file)

        CLOSE(23)...

If the file is currently open in a different process, the first CLOSE will fail.  So it keeps trying until it works (subroutine B closes it when finished).  Is there anything wrong with this trick?

Quote:

DonDilworth wrote:
10      CLOSE (23,ERR=10)
This is, in effect, a "polling loop". Depending upon what else is going on on the computer on which this statement is part of just one process, it could eat up lots of CPU time with little output for the resources consumed. There are many discussions available concerning the tradeoffs between interrupt (or event) driven I/O versus program loop I/O.

The tradeoff here is pretty simple: most of the cores are idle most of the time.  I spawn to some cores to do a job that might run for an hour.  If a given core has to spin for a few milliseconds now and then, it's not an issue.  And the code is very simple.

But now I have a new question:  in my spawn() call, I need the full path to the exe code.  Is there any way for the program to know what that path is?  I don't want to hard-code it, since installations can vary.  What kind of system calls will tell me that path?

See the example code in the entry for COMMAND_ARGUMENT_COUNT in the Intel Fortran reference manual. If the executable is run by double clicking its icon from Windows Explorer, you will get the drive, path and name of the EXE file displayed. If it is run from CMD.EXE, you may need to call GETENV to obtain PATH, and see where along PATH the EXE exists (its name was returned by GET_COMMAND_ARGUMENT).

Super!  It works perfectly, thank you.

If the polling loop is causing a lot of cpu activity, put a very short sleepqq of a handfulll of milliseconds in the loop. that usually makes a big differance.

Ooops... Not perfect.  The path that comes back from GET_COMMAND is

"C:\SYNOPSYSV14\.\Debug\SYNOPSYS200v14.exe"

What the spawnl() needs is

"C:/SYNOPSYSV14/Debug/SYNOPSYS200v14.exe"

So the spawnl() doesn't work.  Is there an easy way to convert that format?  Or should I process the line character by character myself?

That is only because you are invoking from VS with debug, it is the command line being used! If you run from the system you will get a 'normal' path. That is still a valid path I think anyway, the .\ does not add anything but will still work.

There is more that that wrong.  The slashes are backwards and the path string has extra quote marks in it.  If I delete the quotes and change the backslashes to slashes, the spawn works ... but then the command string I pass is not read correctly when the new processes start up.

Is there a C++ call that will recover the path in a friendly fashion?  (I know this is a Fortran forum, but I'll try anything.)

why use spawnlp in fortran, you could use the built in in runqq or systemqq functions for example.

Are you running from debug? The path you are getting I am sure will be what was supplied to the system to invoke the program.

Leave a Comment

Please sign in to add a comment. Not a member? Join today