You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

dynamic_zarch.c 3.4 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. #include "common.h"
  2. #include "cpuid_zarch.h"
  3. #include <stdbool.h>
  4. extern gotoblas_t gotoblas_ZARCH_GENERIC;
  5. #ifdef DYN_Z13
  6. extern gotoblas_t gotoblas_Z13;
  7. #endif
  8. #ifdef DYN_Z14
  9. extern gotoblas_t gotoblas_Z14;
  10. #endif
  11. #define NUM_CORETYPES 4
  12. extern int openblas_verbose();
  13. extern void openblas_warning(int verbose, const char* msg);
  14. char* gotoblas_corename(void) {
  15. #ifdef DYN_Z13
  16. if (gotoblas == &gotoblas_Z13) return cpuname[CPU_Z13];
  17. #endif
  18. #ifdef DYN_Z14
  19. if (gotoblas == &gotoblas_Z14) return cpuname[CPU_Z14];
  20. #endif
  21. if (gotoblas == &gotoblas_ZARCH_GENERIC) return cpuname[CPU_GENERIC];
  22. return "unknown";
  23. }
  24. #ifndef HWCAP_S390_VXE
  25. #define HWCAP_S390_VXE 8192
  26. #endif
  27. /**
  28. * Detect the fitting set of kernels by retrieving the CPU features supported by
  29. * OS from the auxiliary value AT_HWCAP and choosing the set of kernels
  30. * ("coretype") that exploits most of the features and can be compiled with the
  31. * available gcc version.
  32. * Note that we cannot use vector registers on a z13 or newer unless supported
  33. * by the OS kernel (which needs to handle them properly during context switch).
  34. */
  35. static gotoblas_t* get_coretype(void) {
  36. int cpu = detect();
  37. switch(cpu) {
  38. // z14 and z15 systems: exploit Vector Facility (SIMD) and
  39. // Vector-Enhancements Facility 1 (float SIMD instructions), if present.
  40. case CPU_Z14:
  41. #ifdef DYN_Z14
  42. return &gotoblas_Z14;
  43. #endif
  44. // z13: Vector Facility (SIMD for double)
  45. case CPU_Z13:
  46. #ifdef DYN_Z13
  47. return &gotoblas_Z13;
  48. #endif
  49. default:
  50. // fallback in case of missing compiler support, systems before z13, or
  51. // when the OS does not advertise support for the Vector Facility (e.g.,
  52. // missing support in the OS kernel)
  53. return &gotoblas_ZARCH_GENERIC;
  54. }
  55. }
  56. static gotoblas_t* force_coretype(char* coretype) {
  57. int i;
  58. int found = -1;
  59. char message[128];
  60. for (i = 0; i < NUM_CORETYPES; i++)
  61. {
  62. if (!strncasecmp(coretype, cpuname[i], 20))
  63. {
  64. found = i;
  65. break;
  66. }
  67. }
  68. if (found == CPU_Z13) {
  69. #ifdef DYN_Z13
  70. return &gotoblas_Z13;
  71. #else
  72. openblas_warning(1, "Z13 support not compiled in");
  73. return NULL;
  74. #endif
  75. } else if (found == CPU_Z14) {
  76. #ifdef DYN_Z14
  77. return &gotoblas_Z14;
  78. #else
  79. openblas_warning(1, "Z14 support not compiled in");
  80. return NULL;
  81. #endif
  82. } else if (found == CPU_GENERIC) {
  83. return &gotoblas_ZARCH_GENERIC;
  84. }
  85. snprintf(message, 128, "Core not found: %s\n", coretype);
  86. openblas_warning(1, message);
  87. return NULL;
  88. }
  89. void gotoblas_dynamic_init(void) {
  90. char coremsg[128];
  91. char coren[22];
  92. char* p;
  93. if (gotoblas) return;
  94. p = getenv("OPENBLAS_CORETYPE");
  95. if (p)
  96. {
  97. gotoblas = force_coretype(p);
  98. }
  99. else
  100. {
  101. gotoblas = get_coretype();
  102. if (openblas_verbose() >= 2) {
  103. snprintf(coremsg, sizeof(coremsg), "Choosing kernels based on getauxval(AT_HWCAP)=0x%lx\n",
  104. getauxval(AT_HWCAP));
  105. openblas_warning(2, coremsg);
  106. }
  107. }
  108. if (gotoblas == NULL)
  109. {
  110. snprintf(coremsg, 128, "Failed to detect system, falling back to generic z support.\n");
  111. openblas_warning(1, coremsg);
  112. gotoblas = &gotoblas_ZARCH_GENERIC;
  113. }
  114. if (gotoblas && gotoblas->init) {
  115. if (openblas_verbose() >= 2) {
  116. strncpy(coren, gotoblas_corename(), 20);
  117. sprintf(coremsg, "Core: %s\n", coren);
  118. openblas_warning(2, coremsg);
  119. }
  120. gotoblas->init();
  121. }
  122. else {
  123. openblas_warning(0, "OpenBLAS : Architecture Initialization failed. No initialization function found.\n");
  124. exit(1);
  125. }
  126. }
  127. void gotoblas_dynamic_quit(void) {
  128. gotoblas = NULL;
  129. }