Intel® Integrated Performance Primitives
Deliberate problems developing high-performance vision, signal, security, and storage applications.

IPP detects wrong architecture causing Illegal Instruction exception

logantvs
Beginner
2,623 Views

Operating System: Windows 10 Pro
IPP Library version: 2020.0.1 (link to static library)
Compiler: Microsoft Visual Studio 2017 (version 15.4.2) (C++17)
CPU: i7-6700

I run these lines of code below and get the following output:

const IppLibraryVersion* lib;
lib = ippsGetLibVersion();
//print out all the members (see below)

OUPUT>> CPU: k0, Name: ippSP AVX-512F/CD/BW/DQ/VL (k0), Version: 2020.0.1 (r0x35c5ec66), Build Date: Mar  5 2020, major: 2020, majorBuild: 1, minor: 0, build: 902163558

The problem is, the i7-6700 CPU does not support AVX-512 instructions, so it should not be auto-detected as a k0. When running IPP functions like ippiRGBToYCbCr420_8u_C3P3R it will dispatch to use AVX-512 specific instructions like VMOVDQU32 which cause an "illegal instruction" exception to be thrown.

Is there anything else to try here so that the features of the current CPU are correctly understood by IPP? Or is the only recourse to manually set the Intel 64 architecture to L9 with a call to ippSetCpuFeatures()?

0 Kudos
9 Replies
Gennady_F_Intel
Moderator
2,623 Views

Thanks for the report, it looks like a problem. Have you seen the same issue with the previous version of IPP, e.x 2019?

 

0 Kudos
logantvs
Beginner
2,623 Views

I've tested with the latest IPP 2020, IPP 2018 (Version: 2018.0.4 (r60077), Build Date: Aug 15 2018) and IPP 2019 Update 5. I see the same  behavior in all 3 versions. My hardware is detected as being "k0" architecture (ippSP AVX-512F/CD/BW/DQ/VL (k0)).

I've also tried to manually set the cpu features to "L9" architecture by doing this:

// 64-bit CPU architecture features
#define PX_FM ( ippCPUID_MMX | ippCPUID_SSE | ippCPUID_SSE2 )
#define M7_FM ( PX_FM | ippCPUID_SSE3 )
#define U8_FM ( M7_FM | ippCPUID_SSSE3 )
#define N8_FM ( U8_FM | ippCPUID_MOVBE )
#define Y8_FM ( U8_FM | ippCPUID_SSE41 | ippCPUID_SSE42 | ippCPUID_AES | ippCPUID_CLMUL | ippCPUID_SHA )
#define E9_FM ( Y8_FM | ippCPUID_AVX | ippAVX_ENABLEDBYOS | ippCPUID_RDRAND | ippCPUID_F16C )
#define L9_FM ( E9_FM | ippCPUID_MOVBE | ippCPUID_AVX2 | ippCPUID_ADCOX | ippCPUID_RDSEED | ippCPUID_PREFETCHW )
#define N0_FM ( L9_FM | ippCPUID_AVX512F | ippCPUID_AVX512CD | ippCPUID_AVX512PF | ippCPUID_AVX512ER | ippAVX512_ENABLEDBYOS )
#define K0_FM ( L9_FM | ippCPUID_AVX512F | ippCPUID_AVX512CD | ippCPUID_AVX512VL | ippCPUID_AVX512BW | ippCPUID_AVX512DQ | ippAVX512_ENABLEDBYOS )

IppStatus status = ippSetCpuFeatures(L9_FM);

This returns status 49 (ippStsFeatureNotSupported). I expect this because the i7-6700 does not have the ippCPUID_SHA feature. The problem here is that IPP will still dispatch to "k0" implementations even after setting cpu features to "L9" manually.

So I explicitly removed the SHA feature:

const Ipp64u cpuFeatureMask = (L9_FM & (IPP_MAX_64U ^ ippCPUID_SHA));
const IppStatus status = ippSetCpuFeatures(cpuFeatureMask);

Now status is 0 successful. Yet IPP still dispatches to "k0" implementations.

I found that the ippCPUID_AVX2 feature flag is causing IPP to use "k0" instead of "L9".

const Ipp64u cpuFeatureMask = (L9_FM & (IPP_MAX_64U ^ ippCPUID_AVX2 ^ ippCPUID_SHA));
const IppStatus status = ippSetCpuFeatures(cpuFeatureMask);

If I remove ippCPUID_AVX2 from the feature mask, IPP will finally dispatch to the "L9" implementations. This still seems weird since AVX2 is required for "L9". I'm referencing this page.

Anyways, I think that catches you up with where I am at and what things I've tried. Let me know your thoughts. Thank you.

0 Kudos
Gennady_F_Intel
Moderator
2,623 Views

We don't see the problem on our side so far. Running the ippsGetLibVersion() on the same system ( but on Windows Server 2012 R2)

we obtained the following results:

Intel(R) Integrated Performance Primitives

Library IppSP

CPU       : l9

Name      : ippSP AVX2 (l9)

Version   : 2020.0.1 (r0x35c5ec66)

Build date: Mar  5 2020

0 Kudos
Igor_A_Intel
Employee
2,623 Views

Hi Logantvs,

Something is wrong with your IPP installation. It seems like you are using the old version of ippCore library with the latest ippSP library. Could you provide 2 library versions from the same application? ippGetLibVersion() and ippsGetLibVersion? Just to see that ippCore version corresponds to ippSP (or any other domain). Here is my run on i7-6700:

PS C:\Users\iastakh> .\disp
Intel(R) Integrated Performance Primitives
Library IppSP
CPU       : l9
Name      : ippSP AVX2 (l9)
Version   : 2020.0.1 (r0x35c5ec66)
Build date: Mar  5 2020
PS C:\Users\iastakh>

the code itself:

#include "ipps.h"
#include <stdio.h>

int main()
{
    const IppLibraryVersion *lib;

    lib = ippsGetLibVersion();
    printf( "Intel(R) Integrated Performance Primitives\n" );
    printf( "Library IppSP\n" );
    printf( "CPU       : %s\n", lib->targetCpu );
    printf( "Name      : %s\n", lib->Name );
    printf( "Version   : %s\n", lib->Version );
    printf( "Build date: %s\n", lib->BuildDate );
    return 0;
}

and CPU properties are in the attached picture

(something is going wrong - I can't upload my screen-short - sorry - but it is exactly i7-6700)

regards, Igor

0 Kudos
logantvs
Beginner
2,623 Views

Thanks for looking at this Gennady and Igor.

Here is the library version information:

ippGetLibVersion CPU: core, Name: ippCore, Version: 2020.0.1 (r0x35c5ec66), Build Date: Mar  5 2020
ippsGetLibVersion CPU: k0, Name: ippSP AVX-512F/CD/BW/DQ/VL (k0), Version: 2020.0.1 (r0x35c5ec66), Build Date: Mar  5 2020
ippiGetLibVersion CPU: k0, Name: ippIP AVX-512F/CD/BW/DQ/VL (k0), Version: 2020.0.1 (r0x35c5ec66), Build Date: Mar  6 2020

We used Nuget from Visual Studio 2015 to get the package: intelipp.static.win-x64 v2020.1.216
When I tried 2019 and 2018 versions of IPP in the last post, I downloaded them directly from the Intel site and I saw no change in behavior with regards to the architecture dispatching.

We upgraded from IPP 6.1.1.035.

Is there anything else that could be throwing off the architecture detection? I looked through environment variables and didn't see anything related to IPP just in case.

0 Kudos
Igor_A_Intel
Employee
2,623 Views

Hi Logantvs,

Could you insert in your code 

extern int ippJumpIndexForMergedLibs;
 

and print its value before any IPP function call, and then after K0 code is auto dispatched? And also its value when you manually set L9 code?

Or better to insert a loop  - something like

for (int i = 0; i <= 6; i++) {

  ippJumpIndexForMergedLibs = i;

  lib = ippsGetLibVersion();

  printf( "CPU       : %s\n", lib->targetCpu );

}

regards, Igor

 

0 Kudos
Igor_A_Intel
Employee
2,623 Views

Sorry, and also please print "i" value in this loop.

0 Kudos
logantvs
Beginner
2,623 Views

Hi Igor,

I was unable to get the "extern int ippJumpIndexForMergedLibs;" code to link properly. I always received LNK2001 unresolved external symbol "int ippJumpIndexForMergedLibs".

However, in the process of trying to get it to link, I think I found the culprit of the bug. Our project is also using opencv, and it looks like we're linking in some IPP libs from there in addition to the standalone IPP library. 

This is our list of IPP libraries we're linking in. Some I can tell are from opencv and the rest are from IPP.

ippccmt.lib
ippcoremt.lib
ippicvmt.lib    // From opencv2
ippiw.lib       // From opencv2 (though IPP 2020 has a lib called "ipp_iw.lib")
ippimt.lib
ippsmt.lib
ippvmmt.lib

Somehow the project was set up to work correctly when we were using IPP 6, so I'll look into making opencv and IPP 2020 compatible together.
 

0 Kudos
Igor_A_Intel
Employee
2,623 Views

Ok, it is clear now - coremt and ippimt/ippsmt are from different IPP versions. Anyway ippJumpIndexForMergedLibs works on my side:

#include "ipps.h"
#include <stdio.h>

extern int ippJumpIndexForMergedLibs;

int main()
{
    const IppLibraryVersion *lib;

    lib = ippsGetLibVersion();
    printf( "CPU       : %s\n", lib->targetCpu );
    for (int i = 0; i < 6; i++)
    {
        ippJumpIndexForMergedLibs = i;
        lib = ippsGetLibVersion();
        printf("idx = %d; CPU       : %s\n", i, lib->targetCpu);
    }

    return 0;
}

result:

CPU       : l9
idx = 0; CPU       : m7
idx = 1; CPU       : n8
idx = 2; CPU       : y8
idx = 3; CPU       : e9
idx = 4; CPU       : l9
idx = 5; CPU       : k0

C:\!Work\2020disp\disp\x64\Debug\disp.exe (process 40504) exited with code 0.
Press any key to close this window . . .

It is defined in coremt library and is responsible for dispatching. Different versions of library may have different set of supported CPUs and this global index value can mean different code paths. Therefore you should use IPP libraries of only 1 version. "old" and "new" can be incompatible.

regards, Igor.

 

0 Kudos
Reply