Add CPU auto-detecting feature.
This commit is contained in:
parent
70731aa312
commit
5008870893
|
@ -15,10 +15,15 @@ set (OpenVML_FUNC_PREFIX "")
|
|||
set (OpenVML_FUNC_SUFFIX "")
|
||||
|
||||
option(BUILD_SINGLE_THREAD "Only build the single thread" ON)
|
||||
option(AUTO_DETECT_CPU "Auto detect CPU architecture." ON)
|
||||
option(BUILD_OpenVML_TEST "Build Test" ON)
|
||||
|
||||
#####################################################
|
||||
|
||||
if(AUTO_DETECT_CPU)
|
||||
include(${PROJECT_SOURCE_DIR}/cmake/auto_detect_cpu.cmake)
|
||||
endif()
|
||||
|
||||
if (NOT OpenVML_ARCH)
|
||||
set (OpenVML_ARCH "generic")
|
||||
endif(NOT OpenVML_ARCH)
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
/* * Copyright (c) 2014, 2015 Zhang Xianyi
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* * Redistributions in binary form must reproduce the above copyright notice, this
|
||||
* list of conditions and the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
int main()
|
||||
{
|
||||
#if defined(__x86_64__) || defined(__amd64__)
|
||||
printf("x86_64");
|
||||
return 0;
|
||||
#endif
|
||||
//default
|
||||
printf("generic");
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
set (OpenVML_ARCH "generic")
|
||||
set (OpenVML_CPU_CORENAME "generic")
|
||||
|
||||
try_run(arch_detect_result arch_detect_compile_result
|
||||
${PROJECT_BINARY_DIR} ${PROJECT_SOURCE_DIR}/cmake/arch_detect.c
|
||||
RUN_OUTPUT_VARIABLE arch_detect_output
|
||||
)
|
||||
|
||||
if(arch_detect_compile_result)
|
||||
if(arch_detect_result EQUAL 0)
|
||||
set (OpenVML_ARCH ${arch_detect_output})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
#For x86_64
|
||||
if(OpenVML_ARCH STREQUAL "x86_64")
|
||||
try_run(cpu_detect_result cpu_detect_compile_result
|
||||
${PROJECT_BINARY_DIR} ${PROJECT_SOURCE_DIR}/cmake/cpuid_x86.c
|
||||
RUN_OUTPUT_VARIABLE cpu_detect_output
|
||||
)
|
||||
endif()
|
||||
|
||||
if(cpu_detect_compile_result)
|
||||
if(cpu_detect_result EQUAL 0)
|
||||
set (OpenVML_CPU_CORENAME ${cpu_detect_output})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
|
||||
message(STATUS "Detect Arch:" ${OpenVML_ARCH} "\tCPU:" ${OpenVML_CPU_CORENAME})
|
|
@ -0,0 +1,243 @@
|
|||
/* * Copyright (c) 2014, 2015 Zhang Xianyi
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* * Redistributions in binary form must reproduce the above copyright notice, this
|
||||
* list of conditions and the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
#define VENDOR_UNKNOWN 0
|
||||
#define VENDOR_INTEL 1
|
||||
#define VENDOR_AMD 2
|
||||
|
||||
#define CPUNAME_GENERIC 0
|
||||
#define CPUNAME_SANDYBRIDGE 1
|
||||
#define CPUNAME_HASWELL 2
|
||||
//temp set to generic
|
||||
#define CPUNAME_BULLDOZER 0
|
||||
#define CPUNAME_PILEDRIVER 0
|
||||
|
||||
static char *cpuname[] = {
|
||||
"generic",
|
||||
"sandybridge",
|
||||
"haswell",
|
||||
};
|
||||
|
||||
#define BITMASK(a, b, c) ((((a) >> (b)) & (c)))
|
||||
|
||||
static inline void cpuid(int op, int *eax, int *ebx, int *ecx, int *edx){
|
||||
#if defined(__i386__) && defined(__PIC__)
|
||||
__asm__ __volatile__
|
||||
("mov %%ebx, %%edi;"
|
||||
"cpuid;"
|
||||
"xchgl %%ebx, %%edi;"
|
||||
: "=a" (*eax), "=D" (*ebx), "=c" (*ecx), "=d" (*edx) : "a" (op) : "cc");
|
||||
#else
|
||||
__asm__ __volatile__
|
||||
("cpuid": "=a" (*eax), "=b" (*ebx), "=c" (*ecx), "=d" (*edx) : "a" (op) : "cc");
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline int have_cpuid(void){
|
||||
int eax, ebx, ecx, edx;
|
||||
|
||||
cpuid(0, &eax, &ebx, &ecx, &edx);
|
||||
return eax;
|
||||
}
|
||||
|
||||
|
||||
int get_vendor(void){
|
||||
int eax, ebx, ecx, edx;
|
||||
char vendor[13];
|
||||
|
||||
cpuid(0, &eax, &ebx, &ecx, &edx);
|
||||
|
||||
*(int *)(&vendor[0]) = ebx;
|
||||
*(int *)(&vendor[4]) = edx;
|
||||
*(int *)(&vendor[8]) = ecx;
|
||||
vendor[12] = (char)0;
|
||||
|
||||
if (!strcmp(vendor, "GenuineIntel")) return VENDOR_INTEL;
|
||||
if (!strcmp(vendor, "AuthenticAMD")) return VENDOR_AMD;
|
||||
|
||||
if ((eax == 0) || ((eax & 0x500) != 0)) return VENDOR_INTEL;
|
||||
|
||||
return VENDOR_UNKNOWN;
|
||||
}
|
||||
|
||||
|
||||
static inline void xgetbv(int op, int * eax, int * edx){
|
||||
//Use binary code for xgetbv
|
||||
__asm__ __volatile__
|
||||
(".byte 0x0f, 0x01, 0xd0": "=a" (*eax), "=d" (*edx) : "c" (op) : "cc");
|
||||
}
|
||||
|
||||
int support_avx(){
|
||||
int eax, ebx, ecx, edx;
|
||||
int ret=0;
|
||||
|
||||
cpuid(1, &eax, &ebx, &ecx, &edx);
|
||||
if ((ecx & (1 << 28)) != 0 && (ecx & (1 << 27)) != 0 && (ecx & (1 << 26)) != 0){
|
||||
xgetbv(0, &eax, &edx);
|
||||
if((eax & 6) == 6){
|
||||
ret=1; //OS support AVX
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int cpu_detect()
|
||||
{
|
||||
int eax, ebx, ecx, edx;
|
||||
int vendor, family, extend_family, model, extend_model;
|
||||
|
||||
if (!have_cpuid()) return CPUNAME_GENERIC;
|
||||
|
||||
vendor=get_vendor();
|
||||
|
||||
cpuid(1, &eax, &ebx, &ecx, &edx);
|
||||
extend_family = BITMASK(eax, 20, 0xff);
|
||||
extend_model=BITMASK(eax, 16, 0x0f);
|
||||
family=BITMASK(eax, 8, 0x0f);
|
||||
model=BITMASK(eax, 4, 0x0f);
|
||||
|
||||
if (vendor == VENDOR_INTEL){
|
||||
switch (family) {
|
||||
case 0x6:
|
||||
switch (extend_model) {
|
||||
case 2:
|
||||
switch (model) {
|
||||
case 10:
|
||||
case 13:
|
||||
if(support_avx()) {
|
||||
return CPUNAME_SANDYBRIDGE;
|
||||
}else{
|
||||
return CPUNAME_GENERIC; //OS doesn't support AVX
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
switch (model) {
|
||||
case 10:
|
||||
case 14:
|
||||
//Ivy Bridge
|
||||
if(support_avx()) {
|
||||
return CPUNAME_SANDYBRIDGE;
|
||||
}else{
|
||||
return CPUNAME_GENERIC; //OS doesn't support AVX
|
||||
}
|
||||
case 12:
|
||||
case 15:
|
||||
//Haswell.
|
||||
if(support_avx()) {
|
||||
return CPUNAME_HASWELL;
|
||||
}else{
|
||||
return CPUNAME_GENERIC; //OS doesn't support AVX
|
||||
}
|
||||
case 13:
|
||||
//broadwell
|
||||
if(support_avx()) {
|
||||
return CPUNAME_HASWELL;
|
||||
}else{
|
||||
return CPUNAME_GENERIC; //OS doesn't support AVX
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
switch (model) {
|
||||
case 5:
|
||||
case 6:
|
||||
//Haswell.
|
||||
if(support_avx()) {
|
||||
return CPUNAME_HASWELL;
|
||||
}else{
|
||||
return CPUNAME_GENERIC; //OS doesn't support AVX
|
||||
}
|
||||
case 7:
|
||||
case 15:
|
||||
//broadwell
|
||||
if(support_avx()) {
|
||||
return CPUNAME_HASWELL;
|
||||
}else{
|
||||
return CPUNAME_GENERIC; //OS doesn't support AVX
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 5:
|
||||
switch (model) {
|
||||
case 6:
|
||||
//broadwell
|
||||
if(support_avx()) {
|
||||
return CPUNAME_HASWELL;
|
||||
}else{
|
||||
return CPUNAME_GENERIC; //OS doesn't support AVX
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}else if (vendor == VENDOR_AMD){
|
||||
switch (family) {
|
||||
case 0xf:
|
||||
switch (extend_family) {
|
||||
case 6:
|
||||
switch (model) {
|
||||
case 1:
|
||||
if(support_avx())
|
||||
return CPUNAME_BULLDOZER;
|
||||
else
|
||||
return CPUNAME_GENERIC; //OS don't support AVX.
|
||||
case 2:
|
||||
if(support_avx())
|
||||
return CPUNAME_PILEDRIVER;
|
||||
else
|
||||
return CPUNAME_GENERIC; //OS don't support AVX.
|
||||
case 0:
|
||||
//Steamroller. Temp use Piledriver.
|
||||
if(support_avx())
|
||||
return CPUNAME_PILEDRIVER;
|
||||
else
|
||||
return CPUNAME_GENERIC; //OS don't support AVX.
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return CPUNAME_GENERIC;
|
||||
}
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
int cpuname_id;
|
||||
|
||||
cpuname_id=cpu_detect();
|
||||
|
||||
printf("%s", cpuname[cpuname_id]);
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue