Software Archive
Read-only legacy content
17061 Discussions

what is the CPUID test for KNCNI?

Jeff_D_2
Beginner
2,274 Views

I'm using icc (ICC) 15.0.1 20141023 on a Haswell-based system.  My software library has CPU-specific code using either SSE2, SSE41, AVX2, or KNCNI intrinsics.  icc is successfully compiling the KNC code so I need to disable its execution at runtime.  I'm familiar with using CPUID to test at runtime whether an ISA is supported, having done so for SSE2, SSE41, and AVX2.  The intel intrinsics guide lists the CPUID as KNCNI but I can't find any CPUID documentation indicating which bit this corresponds to in the registers.

Which CPUID bit index indicates KNCNI?

0 Kudos
2 Replies
Jeff_D_2
Beginner
2,274 Views

I might be answering my own question here but I would like feedback if the following approach is INCORRECT.

Since the highest value in EAX supported by Knights Corner is 04H (according to appendix B in the Knights Corner Instruction Set Reference
Manual) -- and since it is the only processor that evaluates to 04H -- can I test at runtime if I am running on KNC with the following code?

#include <stdint.h>
#if defined(_MSC_VER)
# include <intrin.h>
#endif

static void run_cpuid(uint32_t eax, uint32_t ecx, uint32_t* abcd)
{
#if defined(_MSC_VER)
    __cpuidex(abcd, eax, ecx);
#else
    uint32_t ebx, edx;
# if defined( __i386__ ) && defined ( __PIC__ )
     /* in case of PIC under 32-bit EBX cannot be clobbered */
    __asm__ ( "movl %%ebx, %%edi \n\t cpuid \n\t xchgl %%ebx, %%edi" : "=D" (ebx),
# else
    __asm__ ( "cpuid" : "+b" (ebx),
# endif
              "+a" (eax), "+c" (ecx), "=d" (edx) );
    abcd[0] = eax; abcd[1] = ebx; abcd[2] = ecx; abcd[3] = edx;
#endif
}

static int check_knc()
{
    uint32_t info[4];
    uint32_t nIds;

    run_cpuid(0, 0, info);
    nIds = info[0];

    /* Highest CPUID Source Operand for KNC Processors is 4 */
    return (nIds == 4);
}

 

0 Kudos
Evan_P_Intel
Employee
2,274 Views

I recommend you use a compile-time test (i.e., an #ifdef in C), not a run-time test. Testing for KNCNI at runtime doesn't really make any sense, since the mere fact that the O/S allowed you to run a binary with the ELF machine type for x86-64 (EM_X86_64 == 0x3e) implies KNCNI is not supported, and similarly its allowing you to run a binary with the ELF machine type for Knights Corner (EM_K1OM == 0xb5) would have implied KNCNI was supported.

There is no CPUID flag bit that indicates support for KNCNI like there is for SSE2 or AVX; the question of compatibility is not that simple. The Knights Corner instruction set is not simply the union of the x86-64 instruction set and KNCNI--there are incompatibilities outside the new vector instructions, and of course the calling conventions are inherently incompatible for functions taking floating point arguments. These incompatibilities are why the ELF machine types for x86-64 and Knights Corner are different; that they are means Linux for Knights Corner will refuse to run programs built for x86-64, and Linux for x86-64 will refuse to run programs built for Knights Corner--similarly to how both will refuse to run programs built for ARM or PowerPC. It also means that the linker will refuse to combine object files for x86-64 and Knights Corner together into a single executable or shared library (although it can be forced to do so, which I guess you've done).

0 Kudos
Reply