GPU 100x schneller als FPU ?

Für allgemeine Fragen zur Programmierung, welche nicht! direkt mit Lazarus zu tun haben.
Antworten
Mathias
Beiträge: 6210
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

GPU 100x schneller als FPU ?

Beitrag von Mathias »

Ich habe ein Array mit 100'000 Floats, welche ich alle durch eine Rechnung durchlasse.
Und von jedem Array-Element, wird 1'000'000 mal die Wurzel gezogen.
Dabei staunte ich nicht schlecht, das die GPU dies 100x schneller erledigt als die CPU.
Wohl verstanden, es arbeitet da keine Highend Gamer-GPU, sondern nur die Intel-Grafik in meinem I7.

Code: Alles auswählen

const
  DataLength = 100000;   
...
start := now;
  glGenBuffers(1, @VBData.TBO);
  glBindBuffer(GL_ARRAY_BUFFER, VBData.TBO);
  glBufferData(GL_ARRAY_BUFFER, Length(feedbacks) * SizeOf(TGLfloat), nil, GL_DYNAMIC_READ);

  glEnable(GL_RASTERIZER_DISCARD);
  glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, VBData.TBO);
  glBeginTransformFeedback(GL_POINTS);

  glDrawArrays(GL_POINTS, 0, Length(Data));

  glEndTransformFeedback;
  glFlush;

  glGetBufferSubData(GL_TRANSFORM_FEEDBACK_BUFFER, 0, Length(feedbacks) * SizeOf(TGLfloat), PGLvoid(feedbacks));
  GPUTime := now - start;

  for i := Length(feedbacks)- 11 to Length(feedbacks)-1 do begin
    WriteLn(feedbacks[i]: 10: 5);
  end;
  WriteLn();

  start := now;
  for i := 0 to Length(feedbacks) - 1 do begin // Einfach mal viel rechen
    feedbacks[i] := Data[i];
    for j := 0 to 1000000 - 1 do begin
      feedbacks[i] := Sqrt(Data[i]) + feedbacks[i];
    end;
  end;
  CPUTime := now - start;


  for i := Length(feedbacks)- 11 to Length(feedbacks)-1 do begin
    WriteLn(feedbacks[i]: 10: 5);
  end;
  WriteLn();

  WriteLn('GPU: ', GPUTime: 20: 20);
  WriteLn('CPU: ', CPUTime: 20: 20);               
OpenGL-Shader

Code: Alles auswählen

#version 420

layout (location =  0) in  float inValue;
layout (location = 10) out float outValue;

void main(void)
{
  outValue = inValue;
  for (int j=0; j < 1000000; j++) {
     outValue = sqrt(inValue) + outValue;
  }
}  
Dies wird ausgespuckt:

Code: Alles auswählen

319254880.00000
319254880.00000
319254912.00000
319254912.00000
319254912.00000
319254912.00000
319255008.00000
319255008.00000
319255008.00000
319255008.00000
319255008.00000

319254880.00000
319254880.00000
319254912.00000
319254912.00000
319254912.00000
319254912.00000
319255008.00000
319255008.00000
319255008.00000
319255008.00000
319255008.00000

GPU: 0.00001927083212649450
CPU: 0.00192648148367879910
Die paar Zahlen gebe ich nur zur Kontrolle aus, zum schauen ob das Ergebnis gleich ist.

Nachtrag: Ist die Array sehr klein, zB. 10, dann ist die CPU ein wenig schneller. Dies liegt wohl am Overhead zum Übertragen de Daten in die GPU.
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Antworten