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

Huge .bss section size difference with IFX vs IFORT?

TomM1
Beginner
1,339 Views

I am building a DLL for the first time with the IFX compiler (2025.1.1).  I have built it for many years with the IFORT compiler (most recently 2021.11.0).  I'm noticing a huge difference in the size of the .bss section of the DLLs produced with each compiler: IFORT is 122MB and IFX is 2.9GB!

 

I'm currently using Visual Studio 2022 in both instances.  I tried to keep the compiler and linker settings as close to identical between the two compilers as I could.  Also, optimization is turned off for my Release builds, so the .bss section is identical size between Release and Debug builds for both compilers.  I'm showing results of Debug builds below.  I'm working on Windows 11, everything is x64.

 

When build with the IFORT compiler, the top of my MAP file showing the size of the .bss section of the DLL is:

 

Preferred load address is 0000000180000000

Start Length Name Class
0001:00000000 0068bf90H .text CODE
0001:0068bf90 00002380H .text$mn CODE
0001:0068e310 00000040H .text$mn$00 CODE
0001:0068e350 000000ddH .text$x CODE
0002:00000000 00000428H .idata$5 DATA
0002:00000428 00000038H .00cfg DATA
0002:00000460 00000008H .CRT$XCA DATA
0002:00000468 00000008H .CRT$XCZ DATA
0002:00000470 00000008H .CRT$XIA DATA
0002:00000478 00000008H .CRT$XIZ DATA
0002:00000480 00000008H .CRT$XPA DATA
0002:00000488 00000008H .CRT$XPZ DATA
0002:00000490 00000008H .CRT$XTA DATA
0002:00000498 00000008H .CRT$XTZ DATA
0002:000004a0 00000000H .gehcont$y DATA
0002:000004a0 00000000H .gfids$y DATA
0002:000004a0 00071360H .rdata DATA
0002:00071800 00000080H .rdata$CastGuardVftablesA DATA
0002:00071880 00000080H .rdata$CastGuardVftablesC DATA
0002:00071900 0000007cH .rdata$voltmd DATA
0002:0007197c 0000031cH .rdata$zzzdbg DATA
0002:00071c98 00000008H .rtc$IAA DATA
0002:00071ca0 00000008H .rtc$IZZ DATA
0002:00071ca8 00000008H .rtc$TAA DATA
0002:00071cb0 00000008H .rtc$TZZ DATA
0002:00071cb8 0000ac48H .xdata DATA
0002:0007c900 00005b5cH .edata DATA
0002:0008245c 000000a0H .idata$2 DATA
0002:000824fc 00000014H .idata$3 DATA
0002:00082510 00000428H .idata$4 DATA
0002:00082938 00000864H .idata$6 DATA
0003:00000000 00028120H .data DATA
0003:00028120 07af39a8H .bss DATA
0004:00000000 00006f60H .pdata DATA
0005:00000000 0004db90H .trace DATA

 

When built with the IFX compiler, the top of my MAP file showing the size of the .bss section of the DLL is: 

 

Preferred load address is 0000000180000000

Start Length Name Class
0001:00000000 0068b962H .text CODE
0001:0068b970 000021d3H .text$mn CODE
0001:0068db50 00000036H .text$mn$00 CODE
0001:0068db90 000000edH .text$x CODE
0002:00000000 00044af0H .rdata DATA
0002:00044b00 00000080H .rdata$CastGuardVftablesA DATA
0002:00044b80 00000080H .rdata$CastGuardVftablesC DATA
0002:00044c88 00000038H .00cfg DATA
0002:00044cc0 00000008H .CRT$XCA DATA
0002:00044cc8 00000008H .CRT$XCZ DATA
0002:00044cd0 00000008H .CRT$XIA DATA
0002:00044cd8 00000008H .CRT$XIZ DATA
0002:00044ce0 00000008H .CRT$XPA DATA
0002:00044ce8 00000008H .CRT$XPZ DATA
0002:00044cf0 00000008H .CRT$XTA DATA
0002:00044cf8 00000008H .CRT$XTZ DATA
0002:0004ba18 00000008H .rtc$IAA DATA
0002:0004ba20 00000008H .rtc$IZZ DATA
0002:0004ba28 00000008H .rtc$TAA DATA
0002:0004ba30 00000008H .rtc$TZZ DATA
0002:0004ba38 00020d24H .xdata DATA
0003:00000000 00026b84H .data DATA
0003:00026b84 b7176d94H .bss DATA
0004:00000000 0001d8a4H .pdata DATA
0005:00000000 00000018H .retplne DATA
0006:00000000 000dadbaH .trace DATA

 

Granted my code features some common blocks, use of /Qsave and /Qinit:zero (see compiler settings below), but still, is it expected that there's such a big difference in the output of the compilers using the same code and same compiler settings?

 

Currently I am having trouble using the DLL built by the IFX compiler with P/Invoke (from C#), which I'm thinking is due to this size exceeding some limitation.  I'd appreciate any insight that could help.  Do I need to drastically re-vamp and re-test my code (it's old), or is there a compiler/linker setting that can restore similar output.

 

Thanks,

Tom.

 

Debug compiler and linker settings for IFORT and IFX:

 

/nologo /debug:full /Od /assume:buffered_io /fpp /assume:nocc_omp /reentrancy:threaded /extend-source:132 /warn:none /Qsave /assume:byterecl /Qinit:zero /fpe:1 /names:uppercase /iface:stdref /iface:mixed_str_len_arg /module:"xxxx" /object:"xxxx" /traceback /libs:dll /threads /dbglibs /4Yportlib /c

 

/OUT:"xxxx.dll" /INCREMENTAL:NO /NOLOGO /LIBPATH:"..\bin\Debug\x64" /MANIFEST /MANIFESTFILE:"xxxx.dll.intermediate.manifest" /MANIFESTUAC:"level='asInvoker' uiAccess='false'" /DEBUG /PDB:"xxxx.pdb" /MAP /MAPINFO:EXPORTS /SUBSYSTEM:WINDOWS /STACK:18000000,8000000 /LARGEADDRESSAWARE /IMPLIB:"xxxx.lib" /DLL

 

0 Kudos
7 Replies
MarcGrodent
Novice
1,311 Views

I have also encountered problems with the size of a DLL when migrating from ifort to ifx:

https://community.intel.com/t5/Intel-Fortran-Compiler/Intel-oneapi-2025-0-quot-Bad-image-quot-error-with-DLL-in-Visual/m-p/1667433#M175077 

 

Do you have the same behaviour?

So far I haven't found a solution to this problem. Except keeping old good ifort for this specific code...

 

0 Kudos
TomM1
Beginner
1,291 Views

Hi Marc,

 

Thanks for pointing out your thread.  Indeed, my observation seems related to yours.  In my case, the extra size is clearly in the BSS section of my DLL, i.e. the uninitialized variables section.  While I'll concede the code may not be the most modern style, which I'm sure is leading to more static memory use than otherwise, I'm more interested in why such a big difference between IFORT and IFX (128MB vs. 2.9GB).  

 

Since my post today, I've tried a couple things:

- compile with /O1 - didn't make a significant difference

- compile with /heap-arrays:100 - didn't make any difference at all

 

I'm hoping that someone with some deeper knowledge of the IFX compiler will know why it is creating the BSS section so much larger than IFORT.

 

 

 

0 Kudos
TomM1
Beginner
1,234 Views

I have spent more time analyzing the linker MAP file for the DLL created by the IFX compiler (the one with the .BSS section nearly 3GB in size).  I now think the size of the .BSS section is directly related to the number of files in my project that include a given file containing common blocks.

 

A bunch of files in my project (25 exactly) contain one or more subroutines which include the line:

 

    include 'DATABASE.CMN'

 

The DATABASE.CMN file contains a bunch of variable definitions and common blocks.  

 

When I look carefully at the symbol offsets in the linker MAP file (which are thankfully sorted by obj file), I can see at the transition from the last variable in a file that contains DATABASE.CMN to the first variable in another file increments the offset by approximately 122MB.  For example, in the following snippet where the variables transition from File1.obj to File2.obj, the offsets jump from 00026bb8 to 07516d40 (122,618,248 bytes).  In this case, File1.obj has subroutines that include DATABASE.CMN (multiple such subroutines).

...

0003:00026bb0   SUBR1$IEND    0000000180723bb0   File1.obj
0003:00026bb4   SUBR1$IST       0000000180723bb4   File1.obj
0003:00026bb8   SUBR1$I            0000000180723bb8   File1.obj
0003:07516d40   SUBR2$IVAL2  0000000187c13d40    File2.obj
0003:07516d44   SUBR2$IVAL1  0000000187c13d44    File2.obj
0003:07516d48   SUBR2$ILEN    0000000187c13d48    File2.obj

...

 

Conversely, when transitioning from files that do not contain subroutines that include DATABASE.CMN, there is no corresponding large jump in the symbol offsets.

 

As I mentioned, there are 25 files in the project with one or more subroutines that include DATABASE.CMN.  In each case the offset when going from one of these files to the next jumps by ~122MB.  So, 122MB * 25 = ~3GB, which is what my overall BSS section length is (B7176D94 == 3,071,765,908).

 

Therefore, I have to conclude that each file (not subroutine) that includes DATABASE.CMN, is adding a copy of the static variables and common blocks that are defined in DATABASE.CMN into the BSS section.

 

Does this make sense?  Again, this didn't seem to be the case with the old compiler.

 

0 Kudos
Ron_Green
Moderator
1,224 Views

I am checking with the team on this one.  I would guess it's this option:
/Qinit:zero

 

we have a couple of efforts underway similar to initializations.  Also another similar issue with .data section size but it's a heavily OO example with CLASS object arguments.  It sounds like your example is using COMMONs which would indicate it's probably older legacy F77 era code. 

0 Kudos
TomM1
Beginner
1,075 Views

Hi Ron,

 

Thanks for looking into this, and I look forward to hearing if the team has any comments.  You are right, the code for my DLL has been around for many years and it is in an older style for the most part.  But it is well-tested, so I'm hoping to find a solution that doesn't involve a major re-factor.

 

Just now I tried toggling some more of the compiler options, including:

 

- turn off /Qinit:zero - no change whatsoever in BSS section size

- change /Qsave to "Default Local Storage" - tiny change in BSS section size but still over 3GB

 

 

 

0 Kudos
TomM1
Beginner
1,031 Views

Update: I have overcome the problem by refactoring my code.  I still think there is something strange happening with the IFX compiler in this scenario, but for the time being I have a workaround.  I'll explain below.

 

As I suspected yesterday, the static variable declarations and COMMON blocks defined in the DATABASE.CMN file were involved.  That file declared dozens of variables and arrays and put them into a number of COMMON blocks so they could be shared between subroutines comprising the DLL.  Any subroutine that needed to use those variables had a line:

 

INCLUDE 'DATABASE.CMN'

 

What I did was change the DATABASE.CMN file into a MODULE (basically wrap the MODULE/END MODULE keywords around the variable declarations and remove the COMMON block statements).  Then I changed all instances of:

 

INCLUDE 'DATABASE.CMN'

to 

USE DATABASE_CMN

 

Once I did that and rebuilt the DLL, the MAP file shows:

 

Preferred load address is 0000000180000000

Start Length Name Class
0001:00000000 0068a4e2H .text CODE
0001:0068a4f0 000021d3H .text$mn CODE
0001:0068c6d0 00000036H .text$mn$00 CODE
0001:0068c710 000000edH .text$x CODE
0002:00000000 00044ad0H .rdata DATA
0002:00044b00 00000080H .rdata$CastGuardVftablesA DATA
0002:00044b80 00000080H .rdata$CastGuardVftablesC DATA
0002:00044c88 00000038H .00cfg DATA
0002:00044cc0 00000008H .CRT$XCA DATA
0002:00044cc8 00000008H .CRT$XCZ DATA
0002:00044cd0 00000008H .CRT$XIA DATA
0002:00044cd8 00000008H .CRT$XIZ DATA
0002:00044ce0 00000008H .CRT$XPA DATA
0002:00044ce8 00000008H .CRT$XPZ DATA
0002:00044cf0 00000008H .CRT$XTA DATA
0002:00044cf8 00000008H .CRT$XTZ DATA
0002:0004ba18 00000008H .rtc$IAA DATA
0002:0004ba20 00000008H .rtc$IZZ DATA
0002:0004ba28 00000008H .rtc$TAA DATA
0002:0004ba30 00000008H .rtc$TZZ DATA
0002:0004ba38 00020d34H .xdata DATA
0003:00000000 000269c4H .data DATA
0003:000269c4 07af26f4H .bss DATA
0004:00000000 0001d8b0H .pdata DATA
0005:00000000 00000018H .retplne DATA
0006:00000000 000da36bH .trace DATA

 

The BSS section is now ~129MB bytes instead of ~3GB, and it can be called fine through P/Invoke.

 

Hopefully that makes sense.  I still think there's something with IFX repeating the variable declarations in the BSS section any time DATABASE.CMN was included in a source file.  It seems to me it was not properly recognizing that the variables were shared
through COMMON blocks.  FORTRAN is not my mother tongue, though, so I'd be interested to hear other's thoughts on this hypothesis.

 

 

0 Kudos
Steve_Lionel
Honored Contributor III
440 Views

Did you initialize the COMMONs in that include file? If so, move the initializations to a BLOCK DATA subprogram - it is a standards violation to initialize a COMMON variable in more than one program unit, but in many cases you can get away with it. Your module solution works too, though you don't even need COMMON anymore once you have the variables in a module.

A caveat regarding BLOCK DATA - ifx has, I think still, a bug in that a BLOCK DATA subprogram won't be linked in from a library even if there is an EXTERNAL declaration for it. If you're not using a static library as part of your build it doesn't matter, but otherwise you would need to explicitly name the object file containing the BLOCK DATA in the linker properties as Additional Dependencies.

Reply