2 * This file is part of the GROMACS molecular simulation package.
4 * Copyright (c) 2012, by the GROMACS development team, led by
5 * David van der Spoel, Berk Hess, Erik Lindahl, and including many
6 * others, as listed in the AUTHORS file in the top-level source
7 * directory and at http://www.gromacs.org.
9 * GROMACS is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public License
11 * as published by the Free Software Foundation; either version 2.1
12 * of the License, or (at your option) any later version.
14 * GROMACS is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with GROMACS; if not, see
21 * http://www.gnu.org/licenses, or write to the Free Software Foundation,
22 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24 * If you want to redistribute modifications to GROMACS, please
25 * consider that scientific software is very special. Version
26 * control is crucial - bugs must be traceable. We will be happy to
27 * consider code for inclusion in the official distribution, but
28 * derived work must not be called official GROMACS. Details are found
29 * in the README & COPYING files - if they are missing, get the
30 * official version at http://www.gromacs.org.
32 * To help us fund GROMACS development, we humbly ask that you cite
33 * the research papers on the package. Check out http://www.gromacs.org.
49 /* MSVC definition for __cpuid() */
53 /* sysconf() definition */
57 #include "gmx_cpuid.h"
61 /* For convenience, and to enable configure-time invocation, we keep all architectures
62 * in a single file, but to avoid repeated ifdefs we set the overall architecture here.
64 #if defined (__i386__) || defined (__x86_64__) || defined (_M_IX86) || defined (_M_X64)
65 # define GMX_CPUID_X86
68 /* Global constant character strings corresponding to our enumerated types */
70 gmx_cpuid_vendor_string[GMX_CPUID_NVENDORS] =
79 gmx_cpuid_feature_string[GMX_CPUID_NFEATURES] =
119 gmx_cpuid_acceleration_string[GMX_CPUID_NACCELERATIONS] =
129 /* Max length of brand string */
130 #define GMX_CPUID_BRAND_MAXLEN 256
133 /* Contents of the abstract datatype */
136 enum gmx_cpuid_vendor vendor;
137 char brand[GMX_CPUID_BRAND_MAXLEN];
141 /* Not using gmx_bool here, since this file must be possible to compile without simple.h */
142 char feature[GMX_CPUID_NFEATURES];
146 /* Simple routines to access the data structure. The initialization routine is
147 * further down since that needs to call other static routines in this file.
149 enum gmx_cpuid_vendor
150 gmx_cpuid_vendor (gmx_cpuid_t cpuid)
152 return cpuid->vendor;
157 gmx_cpuid_brand (gmx_cpuid_t cpuid)
163 gmx_cpuid_family (gmx_cpuid_t cpuid)
165 return cpuid->family;
169 gmx_cpuid_model (gmx_cpuid_t cpuid)
175 gmx_cpuid_stepping (gmx_cpuid_t cpuid)
177 return cpuid->stepping;
181 gmx_cpuid_feature (gmx_cpuid_t cpuid,
182 enum gmx_cpuid_feature feature)
184 return (cpuid->feature[feature]!=0);
190 /* What type of acceleration was compiled in, if any?
191 * This is set from Cmake. Note that the SSE2 and SSE4_1 macros are set for
192 * AVX too, so it is important that they appear last in the list.
194 #ifdef GMX_X86_AVX_256
196 enum gmx_cpuid_acceleration
197 compiled_acc = GMX_CPUID_ACCELERATION_X86_AVX_256;
198 #elif defined GMX_X86_AVX_128_FMA
200 enum gmx_cpuid_acceleration
201 compiled_acc = GMX_CPUID_ACCELERATION_X86_AVX_128_FMA;
202 #elif defined GMX_X86_SSE4_1
204 enum gmx_cpuid_acceleration
205 compiled_acc = GMX_CPUID_ACCELERATION_X86_SSE4_1;
206 #elif defined GMX_X86_SSE2
208 enum gmx_cpuid_acceleration
209 compiled_acc = GMX_CPUID_ACCELERATION_X86_SSE2;
212 enum gmx_cpuid_acceleration
213 compiled_acc = GMX_CPUID_ACCELERATION_NONE;
219 /* Execute CPUID on x86 class CPUs. level sets function to exec, and the
220 * contents of register output is returned. See Intel/AMD docs for details.
222 * This version supports extended information where we can also have an input
223 * value in the ecx register. This is ignored for most levels, but some of them
224 * (e.g. level 0xB on Intel) use it.
227 execute_x86cpuid(unsigned int level,
236 /* Currently CPUID is only supported (1) if we can use an instruction on MSVC, or (2)
237 * if the compiler handles GNU-style inline assembly.
240 #if (defined _MSC_VER)
243 #if (_MSC_VER > 1500) || (_MSC_VER==1500 & _MSC_FULL_VER >= 150030729)
244 /* MSVC 9.0 SP1 or later */
245 __cpuidex(CPUInfo,level,ecxval);
248 __cpuid(CPUInfo,level);
249 /* Set an error code if the user wanted a non-zero ecxval, since we did not have cpuidex */
250 rc = (ecxval>0) ? -1 : 0;
257 #elif (defined GMX_X86_GCC_INLINE_ASM)
258 /* for now this means GMX_X86_GCC_INLINE_ASM should be defined,
259 * but there might be more options added in the future.
265 #if defined(__i386__) && defined(__PIC__)
266 /* Avoid clobbering the global offset table in 32-bit pic code (ebx register) */
267 __asm__ __volatile__ ("xchgl %%ebx, %1 \n\t"
269 "xchgl %%ebx, %1 \n\t"
270 : "+a"(*eax), "+r"(*ebx), "+c"(*ecx), "+d"(*edx));
272 /* i386 without PIC, or x86-64. Things are easy and we can clobber any reg we want :-) */
273 __asm__ __volatile__ ("cpuid \n\t"
274 : "+a"(*eax), "+b"(*ebx), "+c"(*ecx), "+d"(*edx));
279 * Apparently this is an x86 platform where we don't know how to call cpuid.
281 * This is REALLY bad, since we will lose all Gromacs acceleration.
294 /* Identify CPU features common to Intel & AMD - mainly brand string,
295 * version and some features. Vendor has already been detected outside this.
298 cpuid_check_common_x86(gmx_cpuid_t cpuid)
300 int fn,max_stdfn,max_extfn;
301 unsigned int eax,ebx,ecx,edx;
302 char str[GMX_CPUID_BRAND_MAXLEN];
305 /* Find largest standard/extended function input value */
306 execute_x86cpuid(0x0,0,&eax,&ebx,&ecx,&edx);
308 execute_x86cpuid(0x80000000,0,&eax,&ebx,&ecx,&edx);
312 if(max_extfn>=0x80000005)
314 /* Get CPU brand string */
315 for(fn=0x80000002;fn<0x80000005;fn++)
317 execute_x86cpuid(fn,0,&eax,&ebx,&ecx,&edx);
326 /* Remove empty initial space */
332 strncpy(cpuid->brand,p,GMX_CPUID_BRAND_MAXLEN);
336 strncpy(cpuid->brand,"Unknown CPU brand",GMX_CPUID_BRAND_MAXLEN);
339 /* Find basic CPU properties */
342 execute_x86cpuid(0x1,0,&eax,&ebx,&ecx,&edx);
344 cpuid->family = ((eax & 0x0FF00000) >> 20) + ((eax & 0x00000F00) >> 8);
345 /* Note that extended model should be shifted left 4, so only shift right 12 iso 16. */
346 cpuid->model = ((eax & 0x000F0000) >> 12) + ((eax & 0x000000F0) >> 4);
347 cpuid->stepping = (eax & 0x0000000F);
349 /* Feature flags common to AMD and intel */
350 cpuid->feature[GMX_CPUID_FEATURE_X86_SSE3] = (ecx & (1 << 0)) != 0;
351 cpuid->feature[GMX_CPUID_FEATURE_X86_PCLMULDQ] = (ecx & (1 << 1)) != 0;
352 cpuid->feature[GMX_CPUID_FEATURE_X86_SSSE3] = (ecx & (1 << 9)) != 0;
353 cpuid->feature[GMX_CPUID_FEATURE_X86_FMA] = (ecx & (1 << 12)) != 0;
354 cpuid->feature[GMX_CPUID_FEATURE_X86_CX16] = (ecx & (1 << 13)) != 0;
355 cpuid->feature[GMX_CPUID_FEATURE_X86_SSE4_1] = (ecx & (1 << 19)) != 0;
356 cpuid->feature[GMX_CPUID_FEATURE_X86_SSE4_2] = (ecx & (1 << 20)) != 0;
357 cpuid->feature[GMX_CPUID_FEATURE_X86_POPCNT] = (ecx & (1 << 23)) != 0;
358 cpuid->feature[GMX_CPUID_FEATURE_X86_AES] = (ecx & (1 << 25)) != 0;
359 cpuid->feature[GMX_CPUID_FEATURE_X86_AVX] = (ecx & (1 << 28)) != 0;
360 cpuid->feature[GMX_CPUID_FEATURE_X86_F16C] = (ecx & (1 << 29)) != 0;
361 cpuid->feature[GMX_CPUID_FEATURE_X86_RDRND] = (ecx & (1 << 30)) != 0;
363 cpuid->feature[GMX_CPUID_FEATURE_X86_PSE] = (edx & (1 << 3)) != 0;
364 cpuid->feature[GMX_CPUID_FEATURE_X86_MSR] = (edx & (1 << 5)) != 0;
365 cpuid->feature[GMX_CPUID_FEATURE_X86_CX8] = (edx & (1 << 8)) != 0;
366 cpuid->feature[GMX_CPUID_FEATURE_X86_APIC] = (edx & (1 << 9)) != 0;
367 cpuid->feature[GMX_CPUID_FEATURE_X86_CMOV] = (edx & (1 << 15)) != 0;
368 cpuid->feature[GMX_CPUID_FEATURE_X86_CLFSH] = (edx & (1 << 19)) != 0;
369 cpuid->feature[GMX_CPUID_FEATURE_X86_MMX] = (edx & (1 << 23)) != 0;
370 cpuid->feature[GMX_CPUID_FEATURE_X86_SSE2] = (edx & (1 << 26)) != 0;
371 cpuid->feature[GMX_CPUID_FEATURE_X86_HTT] = (edx & (1 << 28)) != 0;
377 cpuid->stepping = -1;
380 if(max_extfn>=0x80000001)
382 execute_x86cpuid(0x80000001,0,&eax,&ebx,&ecx,&edx);
383 cpuid->feature[GMX_CPUID_FEATURE_X86_LAHF_LM] = (ecx & (1 << 0)) != 0;
384 cpuid->feature[GMX_CPUID_FEATURE_X86_PDPE1GB] = (edx & (1 << 26)) != 0;
385 cpuid->feature[GMX_CPUID_FEATURE_X86_RDTSCP] = (edx & (1 << 27)) != 0;
388 if(max_extfn>=0x80000007)
390 execute_x86cpuid(0x80000007,0,&eax,&ebx,&ecx,&edx);
391 cpuid->feature[GMX_CPUID_FEATURE_X86_NONSTOP_TSC] = (edx & (1 << 8)) != 0;
397 /* Detection of AMD-specific CPU features */
399 cpuid_check_amd_x86(gmx_cpuid_t cpuid)
401 int max_stdfn,max_extfn;
402 unsigned int eax,ebx,ecx,edx;
404 cpuid_check_common_x86(cpuid);
406 execute_x86cpuid(0x0,0,&eax,&ebx,&ecx,&edx);
409 execute_x86cpuid(0x80000000,0,&eax,&ebx,&ecx,&edx);
412 if(max_extfn>=0x80000001)
414 execute_x86cpuid(0x80000001,0,&eax,&ebx,&ecx,&edx);
416 cpuid->feature[GMX_CPUID_FEATURE_X86_SSE4A] = (ecx & (1 << 6)) != 0;
417 cpuid->feature[GMX_CPUID_FEATURE_X86_MISALIGNSSE] = (ecx & (1 << 7)) != 0;
418 cpuid->feature[GMX_CPUID_FEATURE_X86_XOP] = (ecx & (1 << 11)) != 0;
419 cpuid->feature[GMX_CPUID_FEATURE_X86_FMA4] = (ecx & (1 << 16)) != 0;
425 /* Detection of Intel-specific CPU features */
427 cpuid_check_intel_x86(gmx_cpuid_t cpuid)
429 unsigned int max_stdfn,max_extfn;
430 unsigned int eax,ebx,ecx,edx;
432 unsigned int max_logical_cores,max_physical_cores;
434 cpuid_check_common_x86(cpuid);
436 execute_x86cpuid(0x0,0,&eax,&ebx,&ecx,&edx);
439 execute_x86cpuid(0x80000000,0,&eax,&ebx,&ecx,&edx);
444 execute_x86cpuid(0x1,0,&eax,&ebx,&ecx,&edx);
445 cpuid->feature[GMX_CPUID_FEATURE_X86_PDCM] = (ecx & (1 << 15)) != 0;
446 cpuid->feature[GMX_CPUID_FEATURE_X86_PCID] = (ecx & (1 << 17)) != 0;
447 cpuid->feature[GMX_CPUID_FEATURE_X86_X2APIC] = (ecx & (1 << 21)) != 0;
448 cpuid->feature[GMX_CPUID_FEATURE_X86_TDT] = (ecx & (1 << 24)) != 0;
453 execute_x86cpuid(0x7,0,&eax,&ebx,&ecx,&edx);
454 cpuid->feature[GMX_CPUID_FEATURE_X86_AVX2] = (ebx & (1 << 5)) != 0;
457 /* Check whether Hyper-Threading is enabled, not only supported */
458 if(cpuid->feature[GMX_CPUID_FEATURE_X86_HTT] && max_stdfn>=4)
460 execute_x86cpuid(0x1,0,&eax,&ebx,&ecx,&edx);
461 max_logical_cores = (ebx >> 16) & 0x0FF;
462 execute_x86cpuid(0x4,0,&eax,&ebx,&ecx,&edx);
463 max_physical_cores = ((eax >> 26) & 0x3F) + 1;
465 /* Clear HTT flag if we only have 1 logical core per physical */
466 if(max_logical_cores/max_physical_cores < 2)
468 cpuid->feature[GMX_CPUID_FEATURE_X86_HTT] = 0;
473 #endif /* GMX_CPUID_X86 */
477 /* Try to find the vendor of the current CPU, so we know what specific
478 * detection routine to call.
480 static enum gmx_cpuid_vendor
481 cpuid_check_vendor(void)
483 enum gmx_cpuid_vendor i,vendor;
484 /* Register data used on x86 */
485 unsigned int eax,ebx,ecx,edx;
486 char vendorstring[13];
488 /* Set default first */
489 vendor = GMX_CPUID_VENDOR_UNKNOWN;
492 execute_x86cpuid(0x0,0,&eax,&ebx,&ecx,&edx);
494 memcpy(vendorstring,&ebx,4);
495 memcpy(vendorstring+4,&edx,4);
496 memcpy(vendorstring+8,&ecx,4);
498 vendorstring[12]='\0';
500 for(i=GMX_CPUID_VENDOR_UNKNOWN;i<GMX_CPUID_NVENDORS;i++)
502 if(!strncmp(vendorstring,gmx_cpuid_vendor_string[i],12))
508 vendor = GMX_CPUID_VENDOR_UNKNOWN;
518 gmx_cpuid_init (gmx_cpuid_t * pcpuid)
523 cpuid = malloc(sizeof(*cpuid));
527 for(i=0;i<GMX_CPUID_NFEATURES;i++)
532 cpuid->vendor = cpuid_check_vendor();
534 switch(cpuid->vendor)
537 case GMX_CPUID_VENDOR_INTEL:
538 cpuid_check_intel_x86(cpuid);
540 case GMX_CPUID_VENDOR_AMD:
541 cpuid_check_amd_x86(cpuid);
545 /* Could not find vendor */
546 strncpy(cpuid->brand,"Unknown CPU brand",GMX_CPUID_BRAND_MAXLEN);
551 for(i=0;i<GMX_CPUID_NFEATURES;i++)
555 cpuid->feature[GMX_CPUID_FEATURE_CANNOTDETECT] = 1;
565 gmx_cpuid_done (gmx_cpuid_t cpuid)
572 gmx_cpuid_formatstring (gmx_cpuid_t cpuid,
578 enum gmx_cpuid_feature feature;
584 "Family: %2d Model: %2d Stepping: %2d\n"
586 gmx_cpuid_vendor_string[gmx_cpuid_vendor(cpuid)],
587 gmx_cpuid_brand(cpuid),
588 gmx_cpuid_family(cpuid),gmx_cpuid_model(cpuid),gmx_cpuid_stepping(cpuid));
593 "Family: %2d Model: %2d Stepping: %2d\n"
595 gmx_cpuid_vendor_string[gmx_cpuid_vendor(cpuid)],
596 gmx_cpuid_brand(cpuid),
597 gmx_cpuid_family(cpuid),gmx_cpuid_model(cpuid),gmx_cpuid_stepping(cpuid));
605 for(feature=GMX_CPUID_FEATURE_CANNOTDETECT;feature<GMX_CPUID_NFEATURES;feature++)
607 if(gmx_cpuid_feature(cpuid,feature)==1)
610 _snprintf(str,n," %s",gmx_cpuid_feature_string[feature]);
612 snprintf(str,n," %s",gmx_cpuid_feature_string[feature]);
621 _snprintf(str,n,"\n");
623 snprintf(str,n,"\n");
632 enum gmx_cpuid_acceleration
633 gmx_cpuid_acceleration_suggest (gmx_cpuid_t cpuid)
635 enum gmx_cpuid_acceleration tmpacc;
637 tmpacc = GMX_CPUID_ACCELERATION_NONE;
639 if(gmx_cpuid_vendor(cpuid)==GMX_CPUID_VENDOR_INTEL)
641 if(gmx_cpuid_feature(cpuid,GMX_CPUID_FEATURE_X86_AVX))
643 tmpacc = GMX_CPUID_ACCELERATION_X86_AVX_256;
645 else if(gmx_cpuid_feature(cpuid,GMX_CPUID_FEATURE_X86_SSE4_1))
647 tmpacc = GMX_CPUID_ACCELERATION_X86_SSE4_1;
649 else if(gmx_cpuid_feature(cpuid,GMX_CPUID_FEATURE_X86_SSE2))
651 tmpacc = GMX_CPUID_ACCELERATION_X86_SSE2;
654 else if(gmx_cpuid_vendor(cpuid)==GMX_CPUID_VENDOR_AMD)
656 if(gmx_cpuid_feature(cpuid,GMX_CPUID_FEATURE_X86_AVX))
658 tmpacc = GMX_CPUID_ACCELERATION_X86_AVX_128_FMA;
660 else if(gmx_cpuid_feature(cpuid,GMX_CPUID_FEATURE_X86_SSE4_1))
662 tmpacc = GMX_CPUID_ACCELERATION_X86_SSE4_1;
664 else if(gmx_cpuid_feature(cpuid,GMX_CPUID_FEATURE_X86_SSE2))
666 tmpacc = GMX_CPUID_ACCELERATION_X86_SSE2;
676 gmx_cpuid_acceleration_check(gmx_cpuid_t cpuid,
681 enum gmx_cpuid_acceleration acc;
683 acc = gmx_cpuid_acceleration_suggest(cpuid);
685 rc = (acc != compiled_acc);
687 gmx_cpuid_formatstring(cpuid,str,1023);
693 "\nDetecting CPU-specific acceleration.\nPresent hardware specification:\n"
695 "Acceleration most likely to fit this hardware: %s\n"
696 "Acceleration selected at GROMACS compile time: %s\n\n",
698 gmx_cpuid_acceleration_string[acc],
699 gmx_cpuid_acceleration_string[compiled_acc]);
706 fprintf(log,"\nBinary not matching hardware - you might be losing performance.\n"
707 "Acceleration most likely to fit this hardware: %s\n"
708 "Acceleration selected at GROMACS compile time: %s\n\n",
709 gmx_cpuid_acceleration_string[acc],
710 gmx_cpuid_acceleration_string[compiled_acc]);
712 printf("Compiled acceleration: %s (Gromacs could use %s on this machine, which is better)\n",
713 gmx_cpuid_acceleration_string[compiled_acc],
714 gmx_cpuid_acceleration_string[acc]);
720 enum gmx_cpuid_x86_smt
721 gmx_cpuid_x86_smt(gmx_cpuid_t cpuid)
724 #if (defined HAVE_SCHED_H && defined HAVE_SCHED_SETAFFINITY && defined HAVE_SYSCONF && defined __linux__)
727 cpu_set_t cpuset,save_cpuset;
729 unsigned int eax,ebx,ecx,edx;
733 if( gmx_cpuid_vendor(cpuid)!=GMX_CPUID_VENDOR_INTEL ||
734 gmx_cpuid_feature(cpuid,GMX_CPUID_FEATURE_X86_HTT)==0)
736 return GMX_CPUID_X86_SMT_DISABLED;
739 /* Check cpuid max standard function */
740 execute_x86cpuid(0x0,0,&eax,&ebx,&ecx,&edx);
742 /* Early CPUs that do not support function 11 do not support SMT either */
745 return GMX_CPUID_X86_SMT_DISABLED;
748 /* If we got here, it is a modern Intel CPU that supports detection, as does our OS */
750 /* How many processors? */
751 nproc = sysconf(_SC_NPROCESSORS_ONLN);
753 apic_id = malloc(sizeof(int)*nproc);
755 sched_getaffinity(0,sizeof(cpu_set_t),&save_cpuset);
757 /* Get x2APIC ID from each hardware thread */
762 sched_setaffinity(0,sizeof(cpu_set_t),&cpuset);
763 execute_x86cpuid(0xB,0,&eax,&ebx,&ecx,&edx);
767 /* Reset affinity to the value it had when calling this routine */
768 sched_setaffinity(0,sizeof(cpu_set_t),&save_cpuset);
770 core_shift_bits = eax & 0x1F;
772 /* Check if there is any other APIC id that is identical to [0], apart from
773 * the hardware thread bit.
776 for(i=1;i<nproc && smt_found==0;i++)
778 smt_found = (apic_id[i]>>core_shift_bits == apic_id[0] >> core_shift_bits);
785 return GMX_CPUID_X86_SMT_ENABLED;
789 return GMX_CPUID_X86_SMT_DISABLED;
792 /* Do the trivial stuff first. If Hyper-Threading isn't even supported it
793 * cannot be enabled, no matter what OS detection we use!
795 if(0==gmx_cpuid_feature(cpuid,GMX_CPUID_FEATURE_X86_HTT))
797 return GMX_CPUID_X86_SMT_DISABLED;
801 return GMX_CPUID_X86_SMT_CANNOTDETECT;
806 return GMX_CPUID_X86_SMT_CANNOTDETECT;
813 #ifdef GMX_CPUID_STANDALONE
814 /* Stand-alone program to enable queries of CPU features from Cmake.
815 * Note that you need to check inline ASM capabilities before compiling and set
816 * -DGMX_X86_GCC_INLINE_ASM for the cpuid instruction to work...
819 main(int argc, char **argv)
822 enum gmx_cpuid_acceleration acc;
828 "Usage:\n\n%s [flags]\n\n"
830 "-vendor Print CPU vendor.\n"
831 "-brand Print CPU brand string.\n"
832 "-family Print CPU family version.\n"
833 "-model Print CPU model version.\n"
834 "-stepping Print CPU stepping version.\n"
835 "-features Print CPU feature flags.\n"
836 "-acceleration Print suggested GROMACS acceleration.\n"
841 gmx_cpuid_init(&cpuid);
843 if(!strncmp(argv[1],"-vendor",3))
845 printf("%s\n",gmx_cpuid_vendor_string[cpuid->vendor]);
847 else if(!strncmp(argv[1],"-brand",3))
849 printf("%s\n",cpuid->brand);
851 else if(!strncmp(argv[1],"-family",3))
853 printf("%d\n",cpuid->family);
855 else if(!strncmp(argv[1],"-model",3))
857 printf("%d\n",cpuid->model);
859 else if(!strncmp(argv[1],"-stepping",3))
861 printf("%d\n",cpuid->stepping);
863 else if(!strncmp(argv[1],"-features",3))
866 for(i=0;i<GMX_CPUID_NFEATURES;i++)
868 if(cpuid->feature[i]==1)
874 printf("%s",gmx_cpuid_feature_string[i]);
879 else if(!strncmp(argv[1],"-acceleration",3))
881 acc = gmx_cpuid_acceleration_suggest(cpuid);
882 fprintf(stdout,"%s\n",gmx_cpuid_acceleration_string[acc]);
885 gmx_cpuid_done(cpuid);