Concurrencia de iOS: no alcanza el máximo teórico cercano a ninguna parte
Soy nuevo en Grand Central Dispatch y he estado realizando algunas pruebas con él procesando algo en una imagen. Básicamente estoy ejecutando un algoritmo en escala de grises tanto secuencialmente como usando GCD y comparando los resultados.
Aquí está el bucle básico:
UInt8 r,g,b;
uint pixelIndex;
for (uint y = 0; y < height; y++) {
for (uint x = 0; x < width; x++) {
pixelIndex = (uint)(y * width + x);
if (pixelIndex+2 < width * height) {
sourceDataPtr = &sourceData[pixelIndex];
r = sourceDataPtr[0+0];
g = sourceDataPtr[0+1];
b = sourceDataPtr[0+2];
int value = (r+g+b) / 3;
if (value > MAX_COLOR_VALUE) {
value = MAX_COLOR_VALUE;
}
targetData[pixelIndex] = value;
self.imageData[pixelIndex] = value;
}
}
}
Simplemente se ejecuta y toma el valor promedio para Rojo, Verde y Azul y lo usa para el valor gris. Muy simple. Ahora la versión paralela básicamente divide la imagen en porciones y luego las calcula por separado. A saber 2, 4, 8, 16 y 32 porciones. Estoy usando el GCD básico, así que pase cada parte como su propio bloque para que se ejecute simultáneamente. Aquí está el código envuelto GCD:
dispatch_group_t myTasks = dispatch_group_create();
for (int startX = 0; startX < width; startX += width/self.numHorizontalSegments) {
for (int startY = 0; startY < height; startY += height/self.numVerticalSegments) {
// For each segment, enqueue a block of code to compute it.
dispatch_group_async(myTasks, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
// grayscale code...
});
}
}
dispatch_group_wait(myTasks, DISPATCH_TIME_FOREVER);
Todo esta funcionando bien. Pero lo que no entiendo es el uso de CPU / aceleración. Ejecutando pruebas en el simulador (que está usando mi CPU de doble núcleo) Estoy obteniendo:
~ 0.0945s de tiempo de ejecución secuencialmente~ 0.0675s de tiempo de ejecución usando GCDEsta es una aceleración de alrededor de ~ 28% (también conocido como 72% del tiempo de la versión secuencial). Teóricamente, en una máquina de 2 núcleos, el 100% de aceleración es el máximo. Así que esto está muy por debajo de eso y no puedo entender por qué.
Superviso el uso de la CPU y alcanza un máximo del 118%. ¿Por qué no se acerca al 200%? Si alguien tiene una idea de lo que debería cambiar, o cuál es el culpable aquí, lo agradecería enormemente.
Mis teorías
No hay suficiente trabajo en la CPU (pero la imagen es de ~ 3,150,000 píxeles)¿No tienes tiempo suficiente para disparar hasta cerca del 200%? ¿Quizás cada subproceso requiere un tiempo de ejecución más largo antes de comenzar a masticar gran parte de la CPU?Pensé que tal vez la sobrecarga era bastante alta, pero una prueba de lanzar 32 bloques vacíos a una cola (también en un grupo) tomó alrededor de ~ 0.0005s como máximo.