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.
29293 Discussions

Unformatted write of function output

dajum
Novice
1,051 Views
I'm writing to an unformatted file but am not getting the expected result. I have an array of real*8 variables and I want them on the file in single precision. I tried using a function that returns a REAL*4 result as follows:

WRITE(98)(R8ToR4FUNC(R8ARRAY(I)),I=1,100))

I expected it to write out the data in REAL*4 yet the file contains REAL*8 as verified by both the size of the file and looking at the file with a HEX file viewer. Note that I use /real_size::64 and /integer_size:64 compilation flags. But the function is explicitly typed to be REAL*4. What do I have to do the get this to be real*4?

An additional question is why when I use the search forum function if I use more than one keyword do I always get zero results? Even if I search with two that I know exist in lots of posts.

Thanks,

Dave
0 Kudos
11 Replies
acar
Beginner
1,051 Views
Hi Dajum,
You could use the elemental intrinsic function REAL to convert from REAL(8) to REAL(4):
PROGRAM TEST_REAL8_TO_REAL4_CONVERSION

REAL(8)::A

OPEN(UNIT=10,FILE='C:\TEMP\TEST.DAT')

A=10.001D0

WRITE(10,*)A,REAL(A)

CLOSE(10)

END
The fileC:\TEMP\TEST.DAT contained the following result:
10.0010000000000 10.00100
Angus.
0 Kudos
IanH
Honored Contributor III
1,051 Views
How does your program differ from the following little snippet? It seems to behave as expected when /real_size:64 is in use.

[fortran]PROGRAM write_some_reals
  IMPLICIT NONE
  REAL :: r_array(10)   ! default real kind
  INTEGER :: i
  !****
  OPEN( 90, FILE='as-is.bin', FORM='UNFORMATTED',  &
      ACTION='WRITE',STATUS='REPLACE' )
  OPEN( 91, FILE='intrinsic.bin', FORM='UNFORMATTED',  &
      ACTION='WRITE',STATUS='REPLACE' )
  OPEN( 92, FILE='user-fun.bin', FORM='UNFORMATTED',  &
      ACTION='WRITE',STATUS='REPLACE' )
  
  r_array = [(REAL(i), i = 1, SIZE(r_array))]   ! default real kind
  
  WRITE (90) r_array                      ! write as default
  WRITE (91) REAL(r_array, 4)             ! change default to 4
  WRITE (92) change_my_reality(r_array)   ! change default to 4
  
  CLOSE(90)
  CLOSE(91)
  CLOSE(92)
CONTAINS
  ELEMENTAL FUNCTION change_my_reality(in) RESULT(out)
    REAL, INTENT(IN) :: in    ! default real kind
    ! fn result
    REAL(4) :: out
    !****
    out = in
  END FUNCTION change_my_reality
END PROGRAM write_some_reals
[/fortran]

[plain]>ifort /check:all /warn:all /integer_size:64 /real_size:64 write_some_reals.f90
Intel Visual Fortran Compiler XE for applications running on IA-32, Version 12.0.2.154 Build 20110112
Copyright (C) 1985-2011 Intel Corporation.  All rights reserved.

Microsoft  Incremental Linker Version 8.00.50727.762
Copyright (C) Microsoft Corporation.  All rights reserved.

-out:write_some_reals.exe
-subsystem:console
write_some_reals.obj

>write_some_reals.exe
>dir *.bin
2011-02-01  11:04 AM                88 as-is.bin
2011-02-01  11:04 AM                48 intrinsic.bin
2011-02-01  11:04 AM                48 user-fun.bin
[/plain]
0 Kudos
dajum
Novice
1,051 Views

acar, you didn't use an unformatted write.

ianh,

Basically my routine is the same as yours. In fact if I run cut down code it runs fine. But in doing so I modified how the variables are declared and where things are running. My code is in a subroutine and the variables come from common blocks. You didn't use individual array elements and explicit loops, while I did. So I can't explain why it doesn't work.I also have loops with zero elements. Maybe it is an optimizer problem as I haven't tried this in a debug build. Looking at the assembly code in the debugger I can't see where it is calling my function SNGLDP that does the R*8 to R*4 conversion except for the first item in the record (TIMEN here: 01400192FA call SNGLDP (14001AD5Ch) ), but the next item (array T with NNOD items) at 14001938E I don't see it. My assembly skills aren't too good with all these new instructions so maybe it inlined something, but I expected to see the function call and don't. Maybe someone else will spot what I can't see in this.

Thanks for looking.

Dave

0 Kudos
Wendy_Doerner__Intel
Valued Contributor I
1,051 Views
Dave,

Your idea of removing optimization options is a good one. If you see the code operating correctly in that case it may be an optimizer bug. Can we in any case get a test case that shows the problem (sounds like you will need to keep the original type definitions)?

------

Wendy

Attaching or including files in a post


0 Kudos
dajum
Novice
1,051 Views

The code I uploaded in my last post is from a debug version and the problem still exists. Could you please examine the assembly code and see if you can tell why the SNGLDP function isn't call except for the first variable in the write statement. Generating a sample that will reproduce the problem and run on your machine is easy if you are willing to install our software and get a demo license. Then I can give you a model that should hopefully reproduce the problem and allow you to compile the source file that normally comes from the library.

Dave

0 Kudos
dajum
Novice
1,051 Views
While I think the function method should work fine, using REAL(T(I),4) does work. So I'm going to move on and use that. But I'm sure there is a bug in the compiler here. Maybe you can use the disassembly I posted to find it.

Dave
0 Kudos
Wendy_Doerner__Intel
Valued Contributor I
1,051 Views
Dave,

Sorry the disassembly does not give me any clues on why the compiler is generating the code and even if it did, to report this to engineering so that they can investigate the cause of the code generation, I do need a working test case that demonstrates the problem including all data definitions and compile line. You understanding your source code would be in a better position to create the test case.

I have done a search in our engineering database to see if we have a related problem, but have not found one. Another suggestion in the case we can not get a test case would be to make sure you are on the latest compiler version: 12.0.2.154


------

Wendy

Attaching or including files in a post



0 Kudos
dajum
Novice
1,051 Views
Wendy,

I'm using 11.1.065 and I can't really check it in the latest version. I'm too far behind to spend a day trying to make a test case for you. Since I have a work-around I'm going to take that path. But I would think you have someone there who could read the assembly I provided and just see if it looks like SNGLDP is being called for each item in the list for the write to NDOUT. That seems like such a little thing to do and yet I don't think you have. Appolgies in advance if you have, but I don't see that answer to my question here. I'm not asking how it got generated, just if matches the source you can see in the sample.

Dave
0 Kudos
Wendy_Doerner__Intel
Valued Contributor I
1,051 Views
Dave,

I did look at the assembly, but it was rather long and without the matching source code and variable definitions, I am not sure that this would help, sinceI can't give the assembly list to engineering.Without a test case we can not pinpoint the phase of the compiler that causes the error.I did ask some engineers more experienced in assembly to give it a look to see if there is anything obvious they can see and asked them to post to this thread if they have more ideas.

Wendy


0 Kudos
Martyn_C_Intel
Employee
1,051 Views
Dave,
I can (and have) constructed a test case that reproduces what you observe. But that doesn't demonstrate a compiler error, it all depends on how the original source is coded. In the example from IanH, the conversion function is in the same module as the caller, so an explicit interface is available (the function will likely also be inlined). His function is elemental, whereas your original example had a separate call for every element.If I place the function in a separate source file, (or in the same source file, but not in a module and not contained), the caller can't see the type of the callee. When you compile with /real_size:64, the function result mayget promoted to 64 bits in the caller, but not in the callee. The solution is to declare the function explicitlyas REAL(4) in the caller, or to make sure that an explicit interface is available.
You might like to check whether this could be happening in your code. But the main point of this example is to emphasize that we can't tell whether the compiler is doing something wrong without seeing the source code from which it starts, or at least enough of the declarations and code structure of the caller and callee to allow us to construct a reproducer.
0 Kudos
dajum
Novice
1,051 Views
Thanks for looking at this Martyn. That explains what is happening. I had caller and callee in the same source file but not contained like it was in the test case (which was all in the disassembly as you could see the function SNGLDP at the bottom). I'm glad I understand why it was failing. Since it works fine using the REAL function I've moved on to other work.
0 Kudos
Reply