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

Issues with Writing Arrays to Shared Memory Handle

Nick_K_6
Beginner
764 Views

I'm using ifort 2015 Update 4 to write some arrays to a disk, and the performance is too slow.  If it matters, I set the default Integer size and default Real size to 8-byte.  I figured, why don’t I write to a shared memory handle instead of directly to a disk file, and then the performance should be better.  I have encountered two problems that I would like some advice.

After my code change, the top performance hit was WriteFile (Windows file writing, which I moved to a separate thread, given that I only have a cheap HDD) – great!  However, the next performance hit is the function for_write_seq_xmit.  So, the first question is, can I do something to improve the performance of this function for_write_seq_xmit?

The second question involves what data is being written from the Fortran arrays, so please refer to the following example Fortran / C++ code.  Suppose I try to write a double-precision array XRCST1(16383); I get the files dum-C.txt and dum-F.txt, and both are identical, and both are 131,072 bytes in size.  (Figure 16384*8 bytes, I assume the extra data is the size of the array.  OK, no problem).  However, once I increase the size of XRCST1 to 16384 (interesting number, 2**14=16384), I get some problems: dum-F.txt is now 131,080 bytes (=16385*8, ok, follows the established pattern), but dum-C.txt is now 131,084 bytes.  So, question #2 is, where are the 4 garbage bytes coming from?  (As you can imagine, another part of my code needs to read back in this file from the disk, so the extra 4 bytes make for some very interesting kind of errors).

 

      program main

      use kernel32

C      use ifposix

C

      interface

        function CallOpener(iOpt)

          !DIR$ATTRIBUTES STDCALL,DECORATE::CallOpener

          !DIR$ATTRIBUTES ALIAS:"CallOpener"::CallOpener

          !DIR$ATTRIBUTES VALUE::iOpt

          integer(8) iOpt,CallOpener

        end function

      end interface

C     

      DOUBLE PRECISION XRCST1

      COMMON/XRCSTH/ XRCST1(16384)

C      COMMON/XRCSTH/ XRCST1(16383)

C

C      integer iArg,iRet

C      integer(4) fd,ierror,inew,iold

C

      EXTERNAL  UOPEN

      INTEGER(INT_PTR_KIND()) UOPEN

     

      XRCST1=1.D0

C      CALL PXFPOSIXIO (1,iold,ierror)

      OPEN(UNIT=10,FILE='C:\data\dum-C.txt',

     &     FORM='UNFORMATTED',USEROPEN=UOpen)

      OPEN(UNIT=11,FILE='C:\data\dum-F.txt',

     &     FORM='UNFORMATTED')

C      write(10,*)"hi"

C      flush(10)

C      CALL PXFFILENO (10,fd,ierror)v

      WRITE(10)XRCST1

      WRITE(11)XRCST1

      close(10)

      close(11)

     

   9  continue

     

      iArg=0

      iRet=CallOpener(iArg)

       

     

      end

     

 

 

#include<Windows.h>

 

 

HANDLE hReadPipe, hWritePipe;

 

 

extern "C" __declspec(dllexport) __int64 __stdcall CallOpener(__int64 iOpt)

{

       HANDLE hResult = CreateFileA("C:\\data\\dum-C.txt", GENERIC_WRITE, FILE_SHARE_READ, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);

      

       char*Bytes=new char[1000000];//1e6

       DWORD bytesRead, bytesWritten;

 

       ReadFile(hReadPipe, Bytes, 1000000, &bytesRead, 0);

       WriteFile(hResult, Bytes, bytesRead, &bytesWritten, 0);

 

       CloseHandle(hReadPipe);

       CloseHandle(hResult);

       delete[]Bytes;

       __int64 result;

       result = 0;

       return result;

}

 

 

extern "C" __declspec(dllexport) void* UOPEN(

       _In_     char*                 lpFileName,

       _In_     DWORD                 dwDesiredAccess,

       _In_     DWORD                 dwShareMode,

       _In_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes,

       _In_     DWORD                 dwCreationDisposition,

       _In_     DWORD                 dwFlagsAndAttributes,

       _In_opt_ HANDLE                hTemplateFile,

       _In_     int&                  UNIT)//,

       //     _In_     int&                  FLEN)

{

       BOOL bResult1 = CreatePipe(&hReadPipe, &hWritePipe, 0, 1000000);//1e6

       DWORD err1 = GetLastError();

       return hWritePipe;

}

 

 

0 Kudos
3 Replies
Steven_L_Intel1
Employee
764 Views

UNFORMATTED adds record length data with SEQUENTIAL access, and very large records may get split up. If you want to just write raw data, then I suggest using ACCESS='STREAM'. Or perhaps RECORDTYPE='FIXED' if all the records are the same size. An alternative is to memory-map the file using CreateFileMapping and MapViewOfFile to allow the data to go directly to disk without involving Fortran I/O. This can be a bit tricky to get right, but if you are saving massive amounts of data it may be useful.

0 Kudos
Nick_K_6
Beginner
764 Views

Thanks Steve.  The data is varying in size, but I will try some of the other options you suggested for performance.

I still don't understand though, why do I get a different-sized file if I let Fortran runtime create the File handle, versus providing my own handle to Fortran?  The "Fortran Runtime Created File Handle" method consistently creates files that I can read back in, while the USEROPEN method does not.

0 Kudos
Steven_L_Intel1
Employee
764 Views

That's a separate problem I'm investigating. We did a lot of work on USEROPEN within the past year, but my own example doesn't work and I have to figure out why.

0 Kudos
Reply