Fragen? Antworten! Siehe auch: Alternativlos
Der Intel Compiler kommt mit neueren glibc Versionen nicht zurecht, da diese einen Bug im Intel Compiler exponieren, der zu "unpredictable system behaviour" führt. Bei uns auf dem HPC Cluster hat sich das so manifestiert, dass unsere Benutzer nach dem Update von CentOS 7.3 auf CentOS 7.4 (dieses Update der glibc exponiert den Intel Bug) bei Simulationen (z.B. mit Kommerziellen "Finite Element" Applikationen wie ANSYS CFX, 3DS Abaqus etc.) falsche Resultate bekamen:Und weil das so grandios ist, kommt hier die technische Erklärung, was da vor sich geht:
- Simulationen die vor dem Update konvergierten tun dies nicht mehr
- Simulationen brechen ab, weil an verschiedenen Stellen NaN's raus kommen wo das nicht sein sollte.
- Bei Simulationen kommen andere Zahlen raus als vor dem Update
Der Bug betrifft potenziell alle mit Intel (Versionen älter als 17.0 Update 5) kompilierten Binaries und Bibliotheken auf Systemen mit Intel CPUs, welche AVX unterstützen.
According to x86-64 psABI, xmm0-xmm7 can be used to pass functionKeine weiteren Fragen, Euer Ehren!
parameters. But ICC also uses xmm8-xmm15 to pass function parameters
which violates x86-64 psABI. As a workaround, you can set environment
variable LD_BIND_NOW=1 by# export LD_BIND_NOW=1
Update: Ich sollte vielleicht mal erklären, was hier vor sich geht. Das ABI ist die Spezifikation dafür, wie man auf einer gegebenen Plattform auf Maschinencode-Ebene Argumente an Funktionen übergibt, und welche Registerinhalte Funktionen überschreiben dürfen, welche sie sichern müssen. Intel hat die Spec gesehen und gesagt "Hold my beer! Die Register dahinten benutzt keiner! Die nehm ich mal!" Das ABI hat aber ganz klar gesagt, dass die eben nicht frei sind.
Das Szenario hier ist: Der Compiler generiert Code für einen Funktionsaufruf. Nun könnte man sagen, hey, wenn der Intel-Compiler beide Seiten erzeugt hat, dann kann ja nichts schiefgehen. Aber es kann halt doch was schiefgehen. Wenn man ein dynamisch gelinktes Binary hat, dann geht der Funktionsaufruf eben nicht zur Funktion, sondern zum Wert in einer Tabelle. Die Einträge in der Tabelle zeigen initial auf ein Stück Code in der glibc, der dann die Adresse für das Symbol herausfindet und in die Tabelle einträgt und dann dahin springt. Die Idee ist, dass so eine Tabelle mehrere Zehntausend Einträge enthalten kann bei großen Binaries, und wenn man die alle beim Start von dem Binary auflöst, dann ergibt das eine spürbare Verzögerung. Denkt hier mal an sowas wie Firefox oder clang von LLVM. Daher löst man erst beim ersten Aufruf auf. Mit LD_BIND_NOW=1 kann man der glibc sagen, dass er bitte alles am Anfang auflösen soll, nicht erst später.
Was hier also passiert ist, ist dass der glibc-Code, der die Symbolauflösung macht, sich an das ABI gehalten hat und die u.a. für ihn reservierte Register benutzt hat. Und da hatte der Intel-Compiler aber Argumente reingetan. Die hat der Code zum Symbolauflösen dann mit Müll überschrieben. Die glibc wäscht hier ihre Hände in Unschuld (und ich hätte nicht gedacht, dass ich DAS nochmal sagen würde). (Danke, Samuel)