En aquest tema, explorarem diverses tècniques per optimitzar el codi i millorar el rendiment dels algorismes. La optimització de codi és crucial per assegurar que els nostres programes s'executin de manera eficient, utilitzant el mínim de recursos possibles.
Objectius del Tema
- Comprendre la importància de l'optimització de codi.
- Aprendre tècniques per identificar colls d'ampolla en el rendiment.
- Aplicar estratègies per millorar l'eficiència del codi.
- Importància de l'Optimització de Codi
1.1. Rendiment i Escalabilitat
- Rendiment: Un codi optimitzat s'executa més ràpidament, millorant l'experiència de l'usuari.
- Escalabilitat: Un codi eficient pot manejar un major volum de dades i usuaris sense degradar el rendiment.
1.2. Ús de Recursos
- Memòria: Reduir l'ús de memòria pot evitar problemes de memòria insuficient.
- CPU: Optimitzar l'ús de la CPU pot reduir el temps de processament i el consum d'energia.
- Identificació de Colls d'Ampolla
2.1. Anàlisi de Perfils (Profiling)
- Eines de Profiling: Utilitza eines com
gprof
,valgrind
, operf
per identificar les parts del codi que consumeixen més temps. - Exemple de Profiling amb
gprof
:gcc -pg -o programa programa.c ./programa gprof programa gmon.out > analysis.txt
2.2. Mesura de Temps d'Execució
- Funcions de Temps: Utilitza funcions com
clock()
en C otime
en Python per mesurar el temps d'execució de diferents parts del codi. - Exemple en Python:
import time start_time = time.time() # Codi a mesurar end_time = time.time() print(f"Temps d'execució: {end_time - start_time} segons")
- Estratègies d'Optimització
3.1. Optimització de Bucles
- Reducció de Complexitat: Simplifica els bucles per reduir la complexitat temporal.
- Exemple:
# Codi no optimitzat for i in range(len(arr)): for j in range(len(arr)): if arr[i] == arr[j]: # Operació # Codi optimitzat for i in range(len(arr)): for j in range(i+1, len(arr)): if arr[i] == arr[j]: # Operació
3.2. Ús de Estructures de Dades Adequades
- Estructures de Dades: Tria l'estructura de dades adequada per a cada problema (llistes, conjunts, diccionaris, etc.).
- Exemple:
# Ús de diccionari per comptar freqüències freq = {} for item in arr: if item in freq: freq[item] += 1 else: freq[item] = 1
3.3. Memòria Cau (Caching)
- Memòria Cau: Emmagatzema resultats de càlculs costosos per reutilitzar-los.
- Exemple en Python amb
functools.lru_cache
:from functools import lru_cache @lru_cache(maxsize=None) def fibonacci(n): if n < 2: return n return fibonacci(n-1) + fibonacci(n-2)
3.4. Paral·lelització
- Paral·lelització: Divideix el treball en múltiples processos o fils per executar-lo simultàniament.
- Exemple en Python amb
multiprocessing
:from multiprocessing import Pool def treball(p): # Codi a paral·lelitzar return resultat if __name__ == "__main__": with Pool(4) as p: resultats = p.map(treball, dades)
Exercicis Pràctics
Exercici 1: Optimització de Bucles
Descripció: Optimitza el següent codi per reduir la seva complexitat temporal.
# Codi original def suma_parella(arr): suma = 0 for i in range(len(arr)): for j in range(len(arr)): if i != j and arr[i] + arr[j] == 10: suma += 1 return suma
Solució:
# Codi optimitzat def suma_parella(arr): suma = 0 complements = set() for num in arr: if 10 - num in complements: suma += 1 complements.add(num) return suma
Exercici 2: Ús de Memòria Cau
Descripció: Implementa una funció per calcular el factorial d'un nombre utilitzant memòria cau.
Solució:
from functools import lru_cache @lru_cache(maxsize=None) def factorial(n): if n == 0: return 1 return n * factorial(n-1)
Resum
En aquest tema, hem après la importància de l'optimització de codi per millorar el rendiment i l'eficiència dels nostres programes. Hem explorat diverses tècniques per identificar colls d'ampolla i aplicar estratègies d'optimització, com ara l'optimització de bucles, l'ús d'estructures de dades adequades, la memòria cau i la paral·lelització. A més, hem practicat aquestes tècniques amb exercicis pràctics per reforçar els conceptes apresos.
Curs d'Anàlisi i Disseny d'Algorismes
Mòdul 1: Introducció als Algorismes
Mòdul 2: Anàlisi d'Algorismes
- Anàlisi de Complexitat Temporal
- Anàlisi de Complexitat Espacial
- Cases de Complexitat: Millor, Pitjor i Promig
Mòdul 3: Estratègies de Disseny d'Algorismes
Mòdul 4: Algorismes Clàssics
- Cerca Binària
- Ordenació per Inserció
- Ordenació per Mescla (Merge Sort)
- Ordenació Ràpida (Quick Sort)
- Algorisme de Dijkstra
- Algorisme de Floyd-Warshall