# OpenCL device timer



## thysol (25. Dezember 2011)

Hi,
Ich moechte gerne die Zeit messen die ein Device braucht um einen Kernel auszufuehren. Das mache ich so:



> ret = clGetEventProfilingInfo(event,CL_PROFILING_COMMAND_START,sizeof(long long),&kernelsStartTime,NULL);
> ret = clGetEventProfilingInfo(event,CL_PROFILING_COMMAND_END,sizeof(long long),&kernelsEndTime,NULL);


Allerdings ist die Zeit die gemessen wird immer gleich, auch wenn der Kernel gefuehlt mehrere Sekunden zum ausfuehren braucht gibt der Timer immer 0.00813 Sekunden als Zeit an. Diese Zeit kriege ich immer, egal ob ich den Kernel auf der CPU oder GPU ausfuehre. Das kann ja wohl nicht sein. Was habe ich falsch gemacht?

Hier ist der gesamte Code:



> ﻿#include <stdio.h>
> #include <stdlib.h>
> #include <pthread.h>
> #ifdef __APPLE__
> ...


----------



## Skysnake (25. Dezember 2011)

Thysol, du misst da wenn ich es richtig in Erinnerung habe nur die Zeit, die benötigt wird, um den Kernel zu starten.

Erstell ein Event, und mess, wann die Queue wieder leer ist. queue.finished() war glaub ich eine Möglichkeit. 

Der Knackpunkt sollte eben sein, das die Sache eben nicht blocking ausgeführt wird.

Das hier funktioniert aber auf jeden Fall:



> // Create command queue using the first device
> ! ! CommandQueue queue = CommandQueue( context, devices[0], CL_QUEUE_PROFILING_ENABLE );
> // Run kernel
> ! ! Event event;
> ...


----------



## thysol (29. Dezember 2011)

Danke fuer die Hilfe. Jetzt kann ich die Kernel ausfuehrungszeit genau messen. Allerdings habe ich jetzt noch ein Problem. Ich moechte 2 Kernel in parallel ausfuehren, also einen auf der CPU und einen auf der GPU. Daher habe ich in C noch einen Thread erstellt wo dann nochmal das OpenCL Zeug gestartet wird nur auf dem anderen Device. Allerdings klappt das nicht, es wird zwar kein Fehler zurueckgeworfen aber immer wenn ich beide Kernel parallel ausfuehre wirft mir OpenCL voellig falsche Zeitwerte die ueberhaupt nicht stimmen koennen, und der Kernel wird auch gefuehlt viel zu schnell ausgefuehrt, daher gehe ich davon aus das er aus irgendeinem Grund ueberhaupt nicht ausgefuehrt wird. Der andere Kernel wird aber immer perfekt ausgefuehrt, die Zeitwerte stimmen auch. Was noch merkwuerdiger ist, es ist immer unterschiedlich welcher Kernel korrekt ausgefuehrt wird. Mal laeuft der auf der CPU korrekt, mal der auf der GPU. Wenn ich den C multi-threading kram weglasse klappt immer alles perfekt, nur wenn ich die Kernel in parallel ausfuehren moechte gibts Probleme. Was mache ich falsch?


----------



## Skysnake (29. Dezember 2011)

OpenCL ist nicht Thread-safe. Daher klappt das nicht 

Also zumindest soweit ich mich erinnern kann ist es nicht Thread-safe.

Versuch es mal mit einer eigenen queue für CPU und GPU. Dann sollte das klappen. Zumindest wenn du nur einen Thread nutzt. Bei mehreren musst du mal schauen.


----------



## thysol (31. Dezember 2011)

Skysnake schrieb:


> OpenCL ist nicht Thread-safe. Daher klappt das nicht
> 
> Also zumindest soweit ich mich erinnern kann ist es nicht Thread-safe.
> 
> Versuch es mal mit einer eigenen queue für CPU und GPU. Dann sollte das klappen. Zumindest wenn du nur einen Thread nutzt. Bei mehreren musst du mal schauen.


 
Wenn ich die Kernels so ausfuehre:



> for(unsigned int i = 0; i < ciDeviceCount; i++)
> {
> ciErrNum = clEnqueueNDRangeKernel(commandQueue_, reduceKernel, 1, 0, globalWorkSize, localWorkSize,
> 0, NULL, &GPUExecution);
> ...


_

Wuerden die dann nicht einem nach dem anderen ausgefuehrt? Oder wuerde das parallel auf der CPU und GPU laufen?_


----------



## Skysnake (31. Dezember 2011)

das sollte dann parallel ausgeführt werden. Zumindest soweit, die CPU die Tasks in die Queue stopfen kann. Braucht ja auch einiges an Zeit.


----------



## thysol (2. Januar 2012)

Skysnake schrieb:


> das sollte dann parallel ausgeführt werden. Zumindest soweit, die CPU die Tasks in die Queue stopfen kann. Braucht ja auch einiges an Zeit.


 
Aus irgendeinem Grund wird das nicht parallel ausgeführt. Das scheint aber ein Bug zu sein:

Khronos.org Message Boards • View topic - non-blocking call to clEnqueueNDRangeKernel?


----------



## Skysnake (2. Januar 2012)

ja geil, und was macht man da jetzt? 


ganz im ernst, erzähl mir bitte die Lösung für das Problem aumen:


----------



## thysol (3. Januar 2012)

Skysnake schrieb:


> ja geil, und was macht man da jetzt?



No ahnung. Vielleicht kann mann mit OpenMPI noch was zurecht biegen, glaube aber kaum. MPI unterscheidet ja zwischen Maschinen, nicht zwischen Devices.



Skysnake schrieb:


> ganz im ernst, erzähl mir bitte die Lösung für das Problem aumen:


 
Wenn ich was herausfinden sollte dann sag ich dir Bescheid.


----------



## Skysnake (3. Januar 2012)

ja wäre wirklich nett. In 2 Wochen kann ich auch mal meinen Dozenten fagen, was da Sache ist. Der macht genau das eigentlich ständig


----------



## Skysnake (27. April 2012)

Sodele, ich steh gerade auch wieder vor dem Problem, dass ich die Ausführungszeit eines Kernels messen muss.

Und TATA ich flieg voll auf die Schnauze weils nicht funktioniert 

Also ich nutze events, und da dann die Times, wann ich das in die Queue rein steckt, und wann das Ergebnis raus kommt.

Ich verwende auch ein clFinish, hilft aber alles nichts. Ich bekomme immer NUR! den gleichen Wert raus, der dann bei 10^13 irgendwo landet, was natürlich totaler quatsch ist, vor allem weil immer genau die gleichen Werte zurückgegeben werden -.-

Das "lustige" an der Sache ist folgendes: Wenn ich in VS2010 das Ding normal im Debugging oder Release mode ausführe kommt ja der Quark raus, wenn ich aber das plugin für VS2010 verwende, mit dem automatisch von allem die profiles angelegt werden, dann werden bei mir auch die richtigen Werte ausgegeben 

DAS ist doch mal geil oder? Jemand ne Idee, was ich falsch mach?

EDIT:

So als ich das hier geschrieben habe, ist mir natürlich gleich die Lösung gekommen. Ich hab eine Zeile übersehen 


```
command_queue[i]=clCreateCommandQueue(context[i], device[i], CL_QUEUE_PROFILING_ENABLE , &err);
```

Man muss ja das Profiling erst aktivieren beim erstellen der Queue 

Sowas vergisst man wirklich VIEL zu einfach. Funktioniert aber ohne Probleme jetzt


----------

