Hayes Technologies - Software Speed Optimization

Geschwindigkeitsoptimierung · Software Speed Optimization · High Performance Computing · Number Crunching · C/C++ · Assembler · SIMD · MMX · SSE · SSE2 · SSE3 · 3DNow!

Fallbeispiele

Diese Seite enthält eine Anzahl von Fallbeispielen für Software-Geschwindigkeits-Optimierung. Die Beispiele sind zur besseren Verständlichkeit bis auf den Kern der Aufgabenstellung reduziert worden.

Bei diesen Beispielen wurden nur die Geschwindigkeitsfaktoren für optimierten Assembler-Code angegeben. Optimierter C/C++ - Code würde zu etwas niedrigeren Zahlen führen.

Bitte wählen Sie unter den folgenden Fallbeispielen:

 

Mehr Fallbeispiele werden hinzugefügt werden, bitte besuchen Sie die Seite regelmäßig!

 

Bildverarbeitung: Binarisierung mit doppelter Schwelle

Dies ist ein Beispiel aus dem Bereich Maschinelles Sehen. Die Aufgabe ist die Erzeugung eines binarisierten Bildes unter Benutzung von 2 Schwellen (untere und obere); die Schwellen werden pro Pixel angegeben in Form eines Bildes. Wenn ein Quell-Pixel zwischen diesen Schwellen liegt, soll das binarisierte Ergebnisbild den Wert 0x0 erhalten, ansonsten 0xff.

Die folgende Funktion ist die C Kernfunktion für das Binarisieren eines Teils einer horizontalen Linie:

 

void BinarizeWithDoubleThreshold(
  const unsigned char sourceimage[],
  const size_t nrpixels,
  const unsigned char lowerthreshold[],
  const unsigned char upperthreshold[],
  unsigned char binarizedimage[]
)
{
  for( size_t i = 0; i < nrpixels; i++ )
    binarizedimage[ i ] = (unsigned char)(
    (sourceimage[ i ] >= lowerthreshold[ i ]  &&
    sourceimage[ i ] < upperthreshold[ i ]) ? 0x0 : 0xff);
}

 

Dies sind die Messergebnisse:

 

System

CPU Pentium III, 1 GHz Mobile Pentium III, 600 MHz Pentium 4, 1.5 GHz Athlon, 1.2 GHz Itanium, 733 MHz
RAM 256 MB SDRAM, 133 MHz 256 MB SDRAM, 100 MHz 256 MB RDRAM, 800 MHz 256 MB SDRAM, 133 MHz 1 GB SDRAM, 133 MHz
Operating System MS Windows 2000 Pro MS Windows XP Pro MS Windows 2000 Pro MS Windows XP Pro MS Windows 2000 Server IA64

Software

Compiler MS Visual C/C++ 6.0 Intel C/C++ 5.0
Optimization switches /G6 /Ox /Ot /Og /Oi /Ob2 /Ox /Ot /Og /Oi /Oa***
Function parameter(s) sourceimage[] = random values
lowerthreshold[] = random values
upperthreshold[] = random values
nrpixels = 1024

Results

Data cached
MPixels / s (C++) 61.49 31.08 17.95 20.17 144.51
MPixels / s (MMX ASM*) 2016.49 988.37 927.30 432.37 NA
Speed-Up Factor 32.79 31.81 51.66 21.44 NA
MPixels / s (SSE2 ASM*) NA** NA** 1439.56 NA** NA**
Speed-Up Factor NA** NA** 85.18 NA** NA**
Data uncached
MPixels / s (C++) 40.87 25.80 16.87 16.46 48.94
MPixels / s (MMX ASM*) 109.99 131.51 339.41 92.62 NA
Speed-Up Factor 2.69 5.10 20.12 5.63 NA
MPixels / s (SSE2 ASM*) NA** NA** 449.90 NA** NA**
Speed-Up Factor NA** NA** 26.67 NA** NA**

* Spezialisierte, separate Funktionen für gecachedte und ungecachedte Daten
** Die SSE2 Befehle sind nur auf dem Pentium 4 und späteren Prozessoren verfügbar
*** Mit Aliasing sind die Ergebnisse deutlich niedriger

 

Hier ist eine Variante: Die Schwellen sind konstant für jedes Pixel:

 
void BinarizeWithDoubleThreshold(
  const unsigned char sourceimage[],
  const size_t nrpixels,
  const unsigned char lowerthreshold,
  const unsigned char upperthreshold,
  unsigned char binarizedimage[]
)
{
  for( size_t i = 0; i < nrpixels; i++ )
    binarizedimage[ i ] = (unsigned char)(
    (sourceimage[ i ] >= lowerthreshold  &&
    sourceimage[ i ] < upperthreshold) ? 0x0 : 0xff);
}

 

Dies sind die korrespondierende Messergebnisse:

System

CPU Pentium III, 1 GHz Mobile Pentium III, 600 MHz Pentium 4, 1.5 GHz Athlon, 1.2 GHz Itanium, 733 MHz
RAM 256 MB SDRAM, 133 MHz 256 MB SDRAM, 100 MHz 256 MB RDRAM, 800 MHz 256 MB SDRAM, 133 MHz 1 GB SDRAM, 133 MHz
Operating System MS Windows 2000 Pro MS Windows XP Pro MS Windows 2000 Pro MS Windows XP Pro MS Windows 2000 Server IA64

Software

Compiler MS Visual C/C++ 6.0 Intel C/C++ 5.0
Optimization switches /G6 /Ox /Ot /Og /Oi /Ob2 /Ox /Ot /Og /Oi /Oa***
Function parameter(s) sourceimage[] = random values
lowerthreshold = 128
upperthreshold = 192
nrpixels = 1024

Results

Data cached
MPixels / s (C++) 65.69 33.10 34.61 68.57 165.34
MPixels / s (MMX ASM*) 3046.02 1524.74 2199.49 5270.02 NA
Speed-Up Factor 46.37 46.07 63.54 76.85 NA
MPixels / s (SSE2 ASM*) NA** NA** 3535.08 NA** NA**
Speed-Up Factor NA** NA** 102.13 NA** NA**
Data uncached
MPixels / s (C++) 50.84 29.19 30.66 46.95 66.27
MPixels / s (MMX ASM*) 259.40 272.42 772.75 352.68 NA
Speed-Up Factor 5.10 9.33 25.21 7.51 NA
MPixels / s (SSE2 ASM*) NA** NA** 993.53 NA** NA**
Speed-Up Factor NA** NA** 32.41 NA** NA**

* Spezialisierte, separate Funktionen für gecachedte und ungecachedte Daten
** Die SSE2 Befehle sind nur auf dem Pentium 4 und späteren Prozessoren verfügbar
*** Mit Aliasing sind die Ergebnisse deutlich niedriger

 

Wie anhand dieser Beispiele zu sehen ist, können die Geschwindigkeitsfaktoren beeindruckend hoch sein, insbesondere, wenn das Speichersystem den Prozessor nicht ausbremst. Wie auch gesehen werden kann, ist, dass langsamere CPUs mehr von der Optimierung profitieren im Falle von speicherintensiven Algorithmen deren Daten nicht im Cache sind.

Zum Seitenanfang zurück

 

Digitale Signalverarbeitung: Künstliches Neuronales Netzwerk

Die (Kern-)Aufgabe hier ist Berechnung der rohen* Aktivierung (bzw. der Ausgabe) eines Neurons. Dies wird durch Summation der Produkte der Ausgaben der Input-Neuronen und der entsprechenden Gewichte berechnet, mit nachfolgender gerundeter Normalisierung. Die Input-Neuronen liefern Werte zwischen 0 und +127, die Gewichte liegen im Bereich -127 .. +127. Es handelt sich also um das Skalarprodukt eines unsigned Byte Arrays mit einem signed Byte Array.

* Der Term roh bezieht sich darauf, dass diese Berechnung nicht den Ausgabe-Wert des Neurons berechnet. Der Ausgabe-Wert wird durch eine Sigmoid-Funktion berechnet, mit dem rohen Wert als Eingabe-Wert.

 
class Neuron_t
{
  const unsigned char * const InputNeuronValues; // Value range == 0 .. +127
  const signed char * const Weights; // Value range = -127 .. +127
  const size_t NrInputNeurons;
public:
  Neuron_t(
  const unsigned char * const inputneuronvalues,
  const signed char * const weights,
  const size_t nrinputneurons ) :
  InputNeuronValues( inputneuronvalues ),
  Weights( weights ),
  NrInputNeurons( nrinputneurons )
  {
  }

  // Compute raw, normalized, rounded output value
  // Return value = -127 .. +127
  signed char ComputeRawOutputValue( void )
  {
    long sum = 0;
    for( size_t z = 0; z < NrInputNeurons; z++ )
      sum += InputNeuronValues[ z ] * Weights[ z ];
    return( (sum + NrInputNeurons * SCHAR_MAX / 2) /
    (NrInputNeurons * SCHAR_MAX) );
  }
};

 

Dies sind die Messergebnisse:

System
CPU Pentium III, 1 GHz Mobile Pentium III, 600 MHz Pentium 4, 1.5 GHz Athlon, 1.2 GHz Itanium, 733 MHz
RAM 256 MB SDRAM, 133 MHz 256 MB SDRAM, 100 MHz 256 MB RDRAM, 800 MHz 256 MB SDRAM, 133 MHz 1 GB SDRAM, 133 MHz
Operating System MS Windows 2000 Pro MS Windows XP Pro MS Windows 2000 Pro MS Windows XP Pro MS Windows 2000 Server IA64
Software
Compiler MS Visual C/C++ 6.0 Intel C/C++ 5.0
Optimization switches /G6 /Ox /Ot /Og /Oi /Ob2 /Ox /Ot /Og /Oi
Class member(s) NrInputNeurons = 1024
Results
Data cached
Mega-Multiply-Adds / s (C++) 242.79 122.06 121.32 197.77 246.03
Mega-Multiply-Adds / s (MMX/SSE1 ASM) 1108.46 560.82 575.55 1160.11 NA
Speed-Up Factor 4.57 4.59 4.74 5.87 NA
Mega-Multiply-Adds / s (SSE2 ASM) NA* NA* 1052.62 NA* NA*
Speed-Up Factor NA* NA* 8.68 NA* NA*
Data uncached
Mega-Multiply-Adds / s (C++) 101.84 71.14 120.36 84.09 95.81
Mega-Multiply-Adds / s (MMX/SSE1 ASM) 283.82 332.46 632.07 235.70 NA
Speed-Up Factor 2.79 4.67 5.25 2.80 NA
Mega-Multiply-Adds / s (SSE2 ASM) NA* NA* 893.39 NA* NA*
Speed-Up Factor NA* NA* 7.42 NA* NA*

* Die SSE2 Befehle sind nur auf dem Pentium 4 und späteren Prozessoren verfügbar

Zum Seitenanfang zurück

Plattformen: x86 · Pentium · Pentium MMX · Pentium II · Pentium III · Pentium 4 · Core · Core 2 · Xeon · Itanium · Athlon · DSPs · Embedded CPUs · Windows · Linux · RT-OS

Besonders profitierende Applikationsgebiete: Bildverarbeitung · Signalverarbeitung · High Performance Computing / Number Crunching · Simulationen · Kompression · Spiele · 3D Software · Gerätetreiber · Multi-Prozessor Systeme · Multi-Computer Systeme / Cluster · Embedded Geräte · Echtzeit-Systeme · Interaktive Systeme · Und viele mehr...