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

Sample Code

JohnNichols
Valued Contributor III
1,902 Views

I was looking to get a template for looking at the error in the WIN program. 

First problem - where are the Intel Fortran Sample files now stored? 

I found a zip file from Steve and this sample gives the following error?  


returnLength = C_SIZEOF(buffer)

The offending code, error occurs on all IFORT and IFX versions. 

Severity Code Description Project File Line Suppression State
Error error #8949: A data entity with the ALLOCATABLE or POINTER attribute is not interoperable. [BUFFER] C:\Users\macne\Downloads\ipsxe2019-samples-win-20190327\compiler_f\Win32\ProcessorInfo\src\ProcessorInfo.f90 81

 

! ==============================================================
!
! SAMPLE SOURCE CODE - SUBJECT TO THE TERMS OF SAMPLE CODE LICENSE AGREEMENT,
! http://software.intel.com/en-us/articles/intel-sample-source-code-license-agreement/
!
! Copyright 2016 Intel Corporation
!
! THIS FILE IS PROVIDED "AS IS" WITH NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT
! NOT LIMITED TO ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
! PURPOSE, NON-INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS.
!
! =============================================================

! ProcessorInfo.f90
!
! Demonstrates the Windows API GetLogicalProcessorInformation, adapted from a Microsoft Developer
! Network example program.  This program also demonstrates the following Fortran 2003/2008 features:
! - Procedure pointers (F2003)
! - C_F_PROCPOINTER (F2003)
! - C_SIZEOF (F2008)
! - POPCNT intrinsic (F2008)
! - Unlimited format repeat count (F2008)
! - ERROR STOP (F2008)
!
! February 7, 2013 - Windows XP 64-bit and Windows Server 2003 don't return information
!                    on Hyperthreading. Add code to warn about that.
!**************************************************************************** 
program ProcessorInfo
    use, intrinsic :: ISO_C_BINDING
    use kernel32

    implicit none
    
    ! Variables
    procedure(GetLogicalProcessorInformation), pointer :: glpi
    type(T_SYSTEM_LOGICAL_PROCESSOR_INFORMATION), allocatable, dimension(:) :: buffer
    integer(DWORD) :: returnLength = 0
    integer :: logicalProcessorCount = 0
    integer :: numaNodeCount = 0
    integer :: processorCoreCount = 0
    integer :: processorCacheCount(3) = [0,0,0]
    integer :: processorPackageCount = 0
    integer(DWORD) :: ret
    integer :: nlpi, lpi_element_length, i
    integer(1), pointer, dimension(:) :: dumpbuf
    
    ! MSDN says that because GetLogicalProcessorInformation is not supported on all versions
    ! of Windows, it suggests getting the address dynamically.  We'll do that here, though
    ! in reality it should not be necessary. The following statement uses only Fortran standard
    ! syntax - it would be a bit simpler to use the integer pointer extension, but this makes a 
    ! good example.
    !
    ! The steps here are:
    ! 1. Call GetModuleHandle to get a handle to the kernel32 DLL which will already be loaded in this image.
    !    Note that this is not the same as LoadLibrary, which assumes that a DLL is not already loaded.
    ! 2. Call GetProcAddress to get the address of GetLogicalProcessorInformation
    ! 3. Use TRANSFER to convert that address to a C_FUNPTR
    ! 4. Use C_F_PROCPOINTER to convert the C_FUNPTR to a Fortran procedure pointer
    
    call c_f_procpointer( &
        transfer( &
            GetProcAddress( &
                GetModuleHandle("kernel32"//C_NULL_CHAR), &
                "GetLogicalProcessorInformation"//C_NULL_CHAR &
                ), &
            C_NULL_FUNPTR &
            ), &
        glpi)
    
    if (.not. associated(glpi)) then
        print *, "GetLogicalProcessorInformation not supported"
        error stop
    end if
     
    ! We don't know in advance the size of the buffer we need. We'll pick a number, allocate it,
    ! and see if that's sufficient.  If not, we'll use the returned size information and reallocate
    ! the buffer to the required size.
    
    allocate (buffer(20))
    lpi_element_length = C_SIZEOF(buffer(1))
    returnLength = C_SIZEOF(buffer)
    print *, "Trying buffer length of ", returnLength
    ret = glpi(buffer, returnLength)
    print *, "Required buffer length is ", returnLength
    if (ret == FALSE) then ! Failed
        if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) then
            deallocate (buffer)
            allocate (buffer(returnLength/lpi_element_length))
            ret = glpi(buffer, returnLength)
            print *, "Reallocated buffer length to ", returnLength
            if (ret == FALSE) then
                print *, "GetLogicalProcessorInformation call failed with error code ", GetLastError()
                error stop
            end if
        else
            print *, "GetLogicalProcessorInformation call failed with error code ", GetLastError()
            error stop
        end if
    end if
    

    ! Now we can iterate through the elements of buffer and see what we can see
    
    do i=1, returnLength / lpi_element_length ! Number of elements in buffer
        select case (buffer(i)%Relationship)
        case(RelationNumaNode)
            ! NUMA nodes return one record of this type
            numaNodeCount = numaNodeCount + 1
        
        case(RelationProcessorCore)
            if (buffer(i)%Flags == 1) then
                processorCoreCount = processorCoreCount + 1
            else
                ! Pre Windows Vista
                processorCoreCount = processorCoreCount + popcnt(buffer(i)%processorMask)
            end if
                            
            ! A Hyperthreaded core supplies more than one logical processor
            logicalProcessorCount = logicalProcessorCount + popcnt(buffer(i)%processorMask)
            
        case(RelationCache)
            ! One cache descriptor for each cache
            if (buffer(i)%Cache%Level > 0 .and. buffer(i)%Cache%Level <= 3) then
                processorCacheCount(buffer(i)%Cache%Level) = processorCacheCount(buffer(i)%Cache%Level) + 1
            else
                print *, "Invalid processor cache level ", buffer(i)%Cache%Level
            end if
            
        case(RelationProcessorPackage)
            !Logical processors share a physical package (socket)
            processorPackageCount = processorPackageCount + 1
            
        case default
            print *, "Unrecognized relationship code ", buffer(i)%Relationship
            
        end select
    end do
    
        
    ! Display the information we collected
        
    print '(A)', "GetLogicalProcessorInformation results:"
    if (processorPackageCount == 0) then
      print '(A)', "  This operating system does not return processor package count nor", &
        & "    information about Hyperthreading"
      processorCoreCount = logicalProcessorCount
    else
      print '(A,I0)',"  Number of physical processor packages: ", processorPackageCount
    end if
    print '(A,I0)',"  Number of NUMA nodes: ", numaNodeCount
    print '(A,I0)',"  Number of processor cores: ", processorCoreCount
    print '(A,I0)',"  Number of logical processors: ", logicalProcessorCount
    print '(A,*(I0,:,"/"))',"  Number of processor L1/L2/L3 caches: ",processorCacheCount

    end program ProcessorInfo

 

 

0 Kudos
14 Replies
Barbara_P_Intel
Employee
1,864 Views

Devorah says to check the FAQ for the link to the samples for Windows.

0 Kudos
Steve_Lionel
Honored Contributor III
1,863 Views

Do keep in mind that these samples have not been updated since 2019, and probably not since 2016. But, they are still useful.

0 Kudos
JohnNichols
Valued Contributor III
1,849 Views

I agree they are really useful,  I have some free time whilst I work on the Smithsonian stuff, their download speed is 2g standard, so I was happily just reading the IFORT manual and when I get to a bit of code, I stick it into a blank console and try it.  If it throws an error I report it, why not it is easy to do and someone may as well fix it. 

I found some WIN Fortran code, I need some Windows Fortan code as a holder program, I grabbed one from the samples, but it will not compile and I CANNOT FIND ANY REFERENCE TO ERROR CODE 8949 in the PDF manuals or online, and the text is so short on the MSVS it does not make sense to me.  

A data entity with the ALLOCATABLE or POINTER attribute is not interoperable. [BUFFER]. So does this mean I cannot use the statement?  It appears to mean that buffer is not transferable to C. 

returnLength = C_SIZEOF(buffer(1))  but if I point to buffer(1) it works, just tried it and then the program calculates how much I need.

So why will c_sizeof work with one element but not the entire array?  

Screenshot 2023-02-24 174115.png

 

thanks the samples pointed to in the FAQ are the same ones that someone loaded into the Forum a few years ago as a zip file. 

 

It appears the ProcessorInfo sample needs to be fixed at line 81 and change buffer to buffer(1)

0 Kudos
JohnNichols
Valued Contributor III
1,838 Views

of course making the 20 a variable then allows line 3 to be a simple multiplication 

allocate (buffer(20))
    lpi_element_length = C_SIZEOF(buffer(1))
    returnLength = C_SIZEOF(buffer)

 

0 Kudos
andrew_4619
Honored Contributor III
1,822 Views

returnLength = size(buffer)*lpi_element_length

 

There error is because a few releases back the standards checking improved. The c_sizeof on the allocatable array is not compliant. A single element is so long as the type is bind(c). If the array was not allocatable it would be ok.

0 Kudos
JohnNichols
Valued Contributor III
1,798 Views

this points to the need to keep the Samples and the manual up to date, the only way to do that is testing.  

it is interesting, you learn a lot looking at other code.  

@Barbara_P_Intel  - how do we submit changes to the samples?  

0 Kudos
Barbara_P_Intel
Employee
1,740 Views

@JohnNichols, good question on changes! As Steve said these samples are old. Steve and others developed them. They should be checked, updated as needed and moved to the oneAPI sample github. The samples update process is not as defined as for the documentation.

If you want just add them to this thread, but I think when the samples get tested against the current compilers the issues will come to light. Sounds like a task for an intern. 

 

0 Kudos
Steve_Lionel
Honored Contributor III
1,731 Views

"Sounds like a task for an intern."

Or, heaven forbid, PV (Product Validation). I spent a LOT of time building batch scripts for the samples so that PV could run them as part of its regular testing. I guess that got dropped.

If one wanted to submit samples to the oneAPI github, how would one go about doing that?

0 Kudos
Barbara_P_Intel
Employee
1,686 Views

@Steve_Lionel, why don't you post samples here. I can gather them and add them to the PSXE samples we need to get migrated.

 

0 Kudos
Steve_Lionel
Honored Contributor III
1,685 Views

I was thinking more of fixing up the existing samples, but, sure. The one I did recently with opening a URL could be used, though there isn't currently an Intel module for SHLWAPI.

Barbara_P_Intel
Employee
1,682 Views

Fixing the existing? Love that! Post here when you've got an update.

0 Kudos
JohnNichols
Valued Contributor III
1,667 Views

 

JohnNichols_0-1677730149119.png

 

I stumbled across this picture today, it made me chuckle and think of this earnest web forum.  

There are always samples in life.  

 

0 Kudos
Steve_Lionel
Honored Contributor III
1,639 Views

I hope Intel appreciates the free work they're getting.

0 Kudos
JohnNichols
Valued Contributor III
1,632 Views

Actually I got a nice note from Karen at Intel thanking me for the suggestions, so it seems a fair trade.  

It is also a good way to practice, I am not at the Fortran level of some of you lot.  

No one really values free work, but I value the free compiler and the friendships on this forum, otherwise you are like I was in the 80s learning LISP on my own.  

I was thinking about a short story about the picture,  

Me:  I reckon they have about a 2 hour head start it is not steaming, but it is warm. 

Jim:  hang on I have a mercury thermometer in my saddle bag

mecej4, I have a chart of horse output temperature against ambient temperature with time, we can put a finer tolerance on their lead.  

Jim:  Has anyone seen Steve, 

Me, Steve is fine, Killer, the black stallion, will stop running sooner or later and bring him back, or wait at the next waterhole. 

Jim: Your small daughter rides Killer, what happened to Steve, 

me: Forgot to tell him Killer does not like spurs, Rebecca never uses spurs.  

 

Fortran in the 1860's. 

Sorry, Steve I could not leave you out of the story.  

0 Kudos
Reply