Optimizar la eficiencia de bucles con directivas
En este paso, aprenderás técnicas para optimizar la eficiencia de los bucles en la programación en C utilizando diversas directivas y estrategias. Exploraremos diferentes enfoques para mejorar el rendimiento y la legibilidad de los bucles.
Vamos a crear un archivo llamado loop_optimization.c en el directorio ~/project para demostrar técnicas de optimización:
cd ~/project
touch loop_optimization.c
#include <stdio.h>
#include <time.h>
#define ARRAY_SIZE 10000
// Function to calculate sum using traditional loop
int traditional_sum(int arr[], int size) {
int sum = 0;
for (int i = 0; i < size; i++) {
sum += arr[i];
}
return sum;
}
// Function to calculate sum using optimized loop
int optimized_sum(int arr[], int size) {
int sum1 = 0, sum2 = 0, sum3 = 0, sum4 = 0;
// Loop unrolling technique
int i;
for (i = 0; i + 4 < size; i += 4) {
sum1 += arr[i];
sum2 += arr[i + 1];
sum3 += arr[i + 2];
sum4 += arr[i + 3];
}
// Handle remaining elements
for (; i < size; i++) {
sum1 += arr[i];
}
return sum1 + sum2 + sum3 + sum4;
}
int main() {
int arr[ARRAY_SIZE];
clock_t start, end;
double cpu_time_used;
// Initialize array
for (int i = 0; i < ARRAY_SIZE; i++) {
arr[i] = i + 1;
}
// Traditional sum
start = clock();
int traditional_result = traditional_sum(arr, ARRAY_SIZE);
end = clock();
cpu_time_used = ((double) (end - start)) / CLOCKS_PER_SEC;
printf("Traditional Sum: %d\n", traditional_result);
printf("Traditional Loop Time: %f seconds\n", cpu_time_used);
// Optimized sum
start = clock();
int optimized_result = optimized_sum(arr, ARRAY_SIZE);
end = clock();
cpu_time_used = ((double) (end - start)) / CLOCKS_PER_SEC;
printf("Optimized Sum: %d\n", optimized_result);
printf("Optimized Loop Time: %f seconds\n", cpu_time_used);
return 0;
}
A continuación, otro ejemplo que demuestra múltiples técnicas de optimización:
#include <stdio.h>
#define MAX_SIZE 1000
int main() {
int numbers[MAX_SIZE];
int even_sum = 0, odd_sum = 0;
// Efficient initialization and summation
for (int i = 0; i < MAX_SIZE; i++) {
numbers[i] = i + 1;
// Conditional sum with minimal branching
even_sum += (numbers[i] % 2 == 0) * numbers[i];
odd_sum += (numbers[i] % 2!= 0) * numbers[i];
}
printf("Sum of Even Numbers: %d\n", even_sum);
printf("Sum of Odd Numbers: %d\n", odd_sum);
return 0;
}
Técnicas de optimización clave demostradas:
- Desenrollado de bucles (loop unrolling) para reducir la sobrecarga del bucle
- Minimización de las predicciones de ramificación
- Combinación de inicialización y procesamiento
- Uso de multiplicación para la suma condicional
Compila y ejecuta los programas con banderas de optimización:
## Compile with basic optimization
gcc -O2 loop_optimization.c -o loop_optimization
./loop_optimization
## Compile with advanced optimization
gcc -O3 loop_optimization.c -o loop_optimization
./loop_optimization
Consejos adicionales de optimización:
- Utiliza las banderas del compilador
-O2 o -O3
- Minimiza las llamadas a funciones dentro de los bucles
- Utiliza tipos de datos adecuados
- Evita cálculos innecesarios
- Considera el movimiento de código invariante del bucle