V_initMT
FunktionInitialisierung der für Mehrkern-Prozessoren optimierten Bibliotheken
Syntax C/C++#include <VecLib.h>
int V_initMT( unsigned nProcCores );
Pascal/Delphiuses VecLib;
function V_initMT( nProcCores:UInt ): IntBool;
BeschreibungDiese Funktion initialisiert die für Mehrkern-Prozessoren optimierten Bibliotheken. Sie liest die Zahl der zur Verfügung stehenden Prozessor-Kerne als Argument und generiert die passende Anzahl von Arbeits-Threads, so dass folgende Aufrufe von OptiVec-Funktionen ihre Berechnungen über die vorhandenen Prozessoren verteilen können. Derzeit kann nProcCores Werte von 2 bis 128 annehmen. Sobald Intel, AMD oder andere Hersteller die Entwicklung von Systemen mit noch mehr Prozessor-Kernen ankündigen, werden auch künftige Versionen von OptiVec Vorkehrungen für so viele Prozessor-Kerne treffen, wie es dann geben mag.

V_initMT muss einmal (und genau einmal) aufgerufen werden, bevor irgendeine Vektor- oder Matrix-Funktion von OptiVec aus der Multi-Prozessor-Bibliothek ausgeführt werden kann. Andersherum schadet aber der Aufruf von V_initMT nicht, wenn Sie eine der (für single-thread optimierten) Allzweck-Bibliotheken verwenden. In diesen Bibliotheken ist V_initMT als leere Funktion enthalten, deren Aufruf nichts bewirkt. Auf diese Weise können Sie zu Test-Zwecken zwischen den verschiedenen Versionen der OptiVec-Bibliotheken hin- und herschalten, ohne sich um die Aktivierung und Deaktivierung von V_initMT kümmern zu müssen.

Auf Rechnern mit vielen Prozessor-Kernen (etwa ab 8 oder 16) ist es u.U. sinnvoll, die Zahl der von jeder einzelnen OptiVec-Funktion beanspruchbaren Threads zu begrenzen. Dies gilt vor allem, wenn eine Anwendung selbst mehrere Arbeits-Threads generiert und aus allen oder mehreren von ihnen OptiVec-Funktionen aufgerufen werden. Im Interesse einer optimalen Ausnutzung der Prozessor-Kapazitäten sollte durch Aufruf von V_limitThreadsPerFunc die Zahl der Threads festgelegt werden, die jeder Aufruf einer OptiVec-Funktion für sich beanspruchen darf. Es empfiehlt sich allerdings, relativ großzügig zu sein. Bei 16 Kernen und vier Anwendungs-Threads etwa sollte man den OptiVec-Funktionen nicht nur 16/4=4, sondern lieber 8 Threads erlauben. Das Betriebssystem wird sich dann um das optimale Scheduling aller Threads kümmern.

Falls Sie die Funktion V_setFPAccuracy verwenden, um die Fließkomma-Genauigkeit der FPU zu modifizieren, muss der Aufruf von V_initMT nach dem Aufruf von V_setFPAccuracy erfolgen. Der Grund hierfür ist, dass V_initMT die zusätzlichen Threads mit denjenigen FPU-Einstellungen erstellt, wie sie bei Aufruf dieser Funktion vorgefunden werden.

nProcCores muss nicht der tatsächlich vorhandenen Zahl der Prozessor-Kerne entsprechen. Zu Test-Zwecken können Sie jeden beliebigen zulässigen Wert eingeben. Optimale Ausführungsgeschwindigkeit wird natürlich nur bei der korrekten Zahl erreicht. Für Anwendungen, die auf Kunden-Systemen laufen, deren Konfiguration außerhalb Ihres Einflussbereiches liegt, sollte die tatsächlich vorhandene Zahl der Prozessor-Kerne durch eine Detektions-Routine ermittelt werden (siehe die Prozessor-Dokumentationen von Intel und AMD). Zur Not kann die automatische Detektion natürlich durch eine Benutzer-Eingabe ersetzt werden.
Obwohl nicht unbedingt erforderlich, empfiehlt es sich, am Programm-Ende die zusätzlichen Threads wieder zu schließen durch Aufruf von V_closeMT.
Die durch V_initMT gesetzte Anzahl der verwendeten Prozessor-Kerne wird in der öffentlichen Variable V_nProcCores abgelegt. Diese ist in C/C++ als (in C++ extern "C") unsigned definiert, in Delphi als UInt. Durch Überprüfung dieser Variablen lässt sich auch feststellen, ob V_initMT bereits aufgerufen wurde.

MT in DLL'sDie Verwendung der Multiprozessor-Bibliotheken in DLL's verlangt eigene Überlegungen:
  • DLL zur Weitergabe an andere:
    Jede einzelne zum Vertrieb bestimmte DLL, die mit der "M"-Bibliothek gebunden wird, muss einen Aufruf von V_initMT in ihrer Initialisierung enthalten.
  • Eine oder wenige DLL's werden von einem Hauptprogramm aus verwendet:
    Auch hier empfiehlt es sich, jede einzelne DLL durch Aufruf von V_initMT zu initialisieren. Dann hat jede DLL ihre eigenen Threads, und das Betriebssystem wird für geeignetes Scheduling sorgen.
  • Mehrere bis viele DLL's werden gleichzeitig verwendet:
    Wenn mehrere oder gar viele DLL's OptiVec-Routinen aufrufen und alle von ein- und demselbem Hauptprogramm aus verwaltet werden, muss man daran denken, die Zahl der gleichzeitig existierenden Threads nicht zu sehr ausufern zu lassen. Hier bieten sich zwei unterschiedliche Strategien an:
    Entweder die weniger zeitkritischen DLL's werden nicht mit der "M"-Bibliothek von OptiVec gebunden, sondern nur diejenigen, bei denen das Auto-Threading wirklich zu einem Performance-Gewinn führt. Dann muss auch nur in letzteren V_initMT aufgerufen werden.
    Oder man installiert ein Callback in jeder einzelnen DLL's, durch das der Thread-Handler des Haupt-Programms auch den OptiVec-Funktionen in den DLL's die Arbeits-Threads zuteilt. Dies ist die beste, aber auch aufwendigste Lösung. Hierzu muss man in jeder betroffenen DLL eine Funktion schreiben und exportieren:
    • C/C++:
      #include <VecLib.h>

      int V_DLLxxx_setThreadHandler( V_THREADHANDLERFUNC ThreadHandler )
      { return V_setThreadHandler( ThreadHandler ); }

      Dabei muss "DLLxxx" eine nur für jeweils eine einzige DLL vergebene Kennung sein.

      Vom Hauptprogramm aus werden dann nacheinander für alle DLL's die eben geschriebenen Funktionen aufgerufen:

      int main( ..... )
      {   ....
          V_initMT( nProcCores ); // Threads im Hauptprogramm initialisieren
          V_DLL001_setThreadHandler( V_threadHandler ); // Callback in DLL 1 installieren
          V_DLL002_setThreadHandler( V_threadHandler ); // Callback in DLL 2 installieren
          // usw. für alle teilnehmenden DLL's
          ....
      }

    • Pascal/Delphi:
      uses VecLib.h;

      function V_DLLxxx_setThreadHandler( ThreadHandler:V_THREADHANDLERFUNC ): IntBool;
      begin V_DLLxxx_setThreadHandler := V_setThreadHandler( ThreadHandler ); end;

      Dabei muss "DLLxxx" eine nur für jeweils eine einzige DLL vergebene Kennung sein.

      Vom Hauptprogramm aus werden dann nacheinander für alle DLL's die eben geschriebenen Funktionen aufgerufen:

      begin   ....
          V_initMT( nProcCores ); // Threads im Hauptprogramm initialisieren
          V_DLL001_setThreadHandler( V_threadHandler ); // Callback in DLL 1 installieren
          V_DLL002_setThreadHandler( V_threadHandler ); // Callback in DLL 2 installieren
          // usw. für alle teilnehmenden DLL's
          ....
      end.

RückgabewertFALSE (0), wenn die Threads fehlerfrei initialisiert werden konnten, andernfalls TRUE (≠ 0)
QuerverweisV_closeMT,  V_setThreadHandler,  V_limitThreadsPerFunc,  Kap. 1.1.2.

VectorLib Inhaltsverzeichnis  OptiVec Home