Actual source code: sseenabled.c
petsc-3.7.7 2017-09-25
2: #include <petscsys.h> /*I "petscsys.h" I*/
4: #if defined(PETSC_HAVE_SSE)
6: #include PETSC_HAVE_SSE
7: #define SSE_FEATURE_FLAG 0x2000000 /* Mask for bit 25 (from bit 0) */
11: PetscErrorCode PetscSSEHardwareTest(PetscBool *flag)
12: {
14: char *vendor;
15: char Intel[13]="GenuineIntel";
16: char AMD[13] ="AuthenticAMD";
19: PetscMalloc1(13,&vendor);
20: strcpy(vendor,"************");
21: CPUID_GET_VENDOR(vendor);
22: if (!strcmp(vendor,Intel) || !strcmp(vendor,AMD)) {
23: /* Both Intel and AMD use bit 25 of CPUID_FEATURES */
24: /* to denote availability of SSE Support */
25: unsigned long myeax,myebx,myecx,myedx;
26: CPUID(CPUID_FEATURES,&myeax,&myebx,&myecx,&myedx);
27: if (myedx & SSE_FEATURE_FLAG) *flag = PETSC_TRUE;
28: else *flag = PETSC_FALSE;
29: }
30: PetscFree(vendor);
31: return(0);
32: }
34: #if defined(PETSC_HAVE_FORK)
35: #include <signal.h>
36: /*
37: Early versions of the Linux kernel disables SSE hardware because
38: it does not know how to preserve the SSE state at a context switch.
39: To detect this feature, try an sse instruction in another process.
40: If it works, great! If not, an illegal instruction signal will be thrown,
41: so catch it and return an error code.
42: */
43: #define PetscSSEOSEnabledTest(arg) PetscSSEOSEnabledTest_Linux(arg)
45: static void PetscSSEDisabledHandler(int sig)
46: {
47: signal(SIGILL,SIG_IGN);
48: exit(-1);
49: }
53: PetscErrorCode PetscSSEOSEnabledTest_Linux(PetscBool *flag)
54: {
55: int status, pid = 0;
58: signal(SIGILL,PetscSSEDisabledHandler);
59: pid = fork();
60: if (pid==0) {
61: SSE_SCOPE_BEGIN;
62: XOR_PS(XMM0,XMM0);
63: SSE_SCOPE_END;
64: exit(0);
65: } else wait(&status);
66: if (!status) *flag = PETSC_TRUE;
67: else *flag = PETSC_FALSE;
68: return(0);
69: }
71: #else
72: /*
73: Windows 95/98/NT4 should have a Windows Update/Service Patch which enables this hardware.
74: Windows ME/2000 doesn't disable SSE Hardware
75: */
76: #define PetscSSEOSEnabledTest(arg) PetscSSEOSEnabledTest_TRUE(arg)
77: #endif
81: PetscErrorCode PetscSSEOSEnabledTest_TRUE(PetscBool *flag)
82: {
84: if (flag) *flag = PETSC_TRUE;
85: return(0);
86: }
88: #else /* Not defined PETSC_HAVE_SSE */
90: #define PetscSSEHardwareTest(arg) PetscSSEEnabledTest_FALSE(arg)
91: #define PetscSSEOSEnabledTest(arg) PetscSSEEnabledTest_FALSE(arg)
95: PetscErrorCode PetscSSEEnabledTest_FALSE(PetscBool *flag)
96: {
98: if (flag) *flag = PETSC_FALSE;
99: return(0);
100: }
102: #endif /* defined PETSC_HAVE_SSE */
106: /*@C
107: PetscSSEIsEnabled - Determines if Intel Streaming SIMD Extensions (SSE) to the x86 instruction
108: set can be used. Some operating systems do not allow the use of these instructions despite
109: hardware availability.
111: Collective on MPI_Comm
113: Input Parameter:
114: . comm - the MPI Communicator
116: Output Parameters:
117: . lflag - Local Flag: PETSC_TRUE if enabled in this process
118: . gflag - Global Flag: PETSC_TRUE if enabled for all processes in comm
120: Notes:
121: NULL can be specified for lflag or gflag if either of these values are not desired.
123: Options Database Keys:
124: . -disable_sse - Disable use of hand tuned Intel SSE implementations
126: Level: developer
127: @*/
128: static PetscBool petsc_sse_local_is_untested = PETSC_TRUE;
129: static PetscBool petsc_sse_enabled_local = PETSC_FALSE;
130: static PetscBool petsc_sse_global_is_untested = PETSC_TRUE;
131: static PetscBool petsc_sse_enabled_global = PETSC_FALSE;
132: PetscErrorCode PetscSSEIsEnabled(MPI_Comm comm,PetscBool *lflag,PetscBool *gflag)
133: {
135: PetscBool disabled_option;
138: if (petsc_sse_local_is_untested && petsc_sse_global_is_untested) {
139: disabled_option = PETSC_FALSE;
141: PetscOptionsGetBool(NULL,NULL,"-disable_sse",&disabled_option,NULL);
142: if (disabled_option) {
143: petsc_sse_local_is_untested = PETSC_FALSE;
144: petsc_sse_enabled_local = PETSC_FALSE;
145: petsc_sse_global_is_untested = PETSC_FALSE;
146: petsc_sse_enabled_global = PETSC_FALSE;
147: }
149: if (petsc_sse_local_is_untested) {
150: PetscSSEHardwareTest(&petsc_sse_enabled_local);
151: if (petsc_sse_enabled_local) {
152: PetscSSEOSEnabledTest(&petsc_sse_enabled_local);
153: }
154: petsc_sse_local_is_untested = PETSC_FALSE;
155: }
157: if (gflag && petsc_sse_global_is_untested) {
158: MPIU_Allreduce(&petsc_sse_enabled_local,&petsc_sse_enabled_global,1,MPIU_BOOL,MPI_LAND,comm);
160: petsc_sse_global_is_untested = PETSC_FALSE;
161: }
162: }
164: if (lflag) *lflag = petsc_sse_enabled_local;
165: if (gflag) *gflag = petsc_sse_enabled_global;
166: return(0);
167: }