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

Issues with Writing Arrays to Shared Memory Handle

Nick_K_6
Beginner
937 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
937 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
937 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
937 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