La programació paral·lela i concurrent en Prolog permet executar múltiples processos simultàniament, millorant així l'eficiència i el rendiment de les aplicacions. Aquest tema és especialment rellevant en sistemes amb múltiples nuclis de processador o en aplicacions que requereixen un alt rendiment.
Conceptes Clau
- Programació Paral·lela vs. Concurrent
- Programació Paral·lela: Execució simultània de múltiples tasques en diferents nuclis de processador.
- Programació Concurrent: Gestió de múltiples tasques que poden no executar-se exactament al mateix temps, però que es gestionen de manera que semblin simultànies.
- Models de Programació Concurrent
- Model de Fil: Utilitza fils d'execució per gestionar tasques concurrents.
- Model d'Actors: Utilitza actors que poden enviar i rebre missatges per gestionar la concurrència.
- Model de Dades Compartides: Utilitza variables compartides entre diferents tasques.
Implementació en Prolog
- Llibreries i Eines
Prolog ofereix diverses llibreries per gestionar la concurrència i la paral·lelització. Algunes de les més utilitzades són:
- Threads: Llibreria per gestionar fils d'execució.
- Concurrent Goals: Llibreria per executar objectius de manera concurrent.
- Creació de Fils
Per crear un fil en Prolog, es pot utilitzar el predicat thread_create/3
.
% Exemple de creació d'un fil :- use_module(library(threads)). task :- writeln('Aquesta és una tasca en un fil separat'). start_thread :- thread_create(task, Id, []), writeln('Fil creat amb ID: '), writeln(Id).
- Sincronització de Fils
La sincronització és crucial per evitar condicions de carrera i assegurar que els fils comparteixin dades de manera segura. Prolog proporciona mecanismes com semàfors i variables compartides.
% Exemple d'ús de semàfors :- use_module(library(sem)). critical_section :- writeln('Entrant a la secció crítica'), sleep(1), writeln('Sortint de la secció crítica'). start_synchronized_threads :- sem_create(sem, 1), thread_create((sem_acquire(sem), critical_section, sem_release(sem)), _, []), thread_create((sem_acquire(sem), critical_section, sem_release(sem)), _, []).
- Comunicació entre Fils
Els fils poden comunicar-se entre ells utilitzant cues de missatges.
% Exemple de comunicació entre fils :- use_module(library(threads)). producer(Queue) :- thread_send_message(Queue, 'Missatge des del productor'). consumer(Queue) :- thread_get_message(Queue, Message), writeln('Consumidor ha rebut: '), writeln(Message). start_communication :- message_queue_create(Queue), thread_create(producer(Queue), _, []), thread_create(consumer(Queue), _, []).
Exercicis Pràctics
Exercici 1: Creació de Fils
Crea un programa que iniciï tres fils, cadascun dels quals imprimeixi un missatge diferent.
Solució
task1 :- writeln('Fil 1: Hola!'). task2 :- writeln('Fil 2: Com estàs?'). task3 :- writeln('Fil 3: Adéu!'). start_threads :- thread_create(task1, _, []), thread_create(task2, _, []), thread_create(task3, _, []).
Exercici 2: Sincronització amb Semàfors
Modifica l'exemple de sincronització per assegurar que només un fil pugui accedir a la secció crítica al mateix temps.
Solució
critical_section :- writeln('Entrant a la secció crítica'), sleep(1), writeln('Sortint de la secció crítica'). start_synchronized_threads :- sem_create(sem, 1), thread_create((sem_acquire(sem), critical_section, sem_release(sem)), _, []), thread_create((sem_acquire(sem), critical_section, sem_release(sem)), _, []), thread_create((sem_acquire(sem), critical_section, sem_release(sem)), _, []).
Exercici 3: Comunicació entre Fils
Crea un programa on un productor enviï tres missatges a un consumidor, i el consumidor imprimeixi cada missatge rebut.
Solució
producer(Queue) :- thread_send_message(Queue, 'Missatge 1'), thread_send_message(Queue, 'Missatge 2'), thread_send_message(Queue, 'Missatge 3'). consumer(Queue) :- thread_get_message(Queue, Message1), writeln('Consumidor ha rebut: '), writeln(Message1), thread_get_message(Queue, Message2), writeln('Consumidor ha rebut: '), writeln(Message2), thread_get_message(Queue, Message3), writeln('Consumidor ha rebut: '), writeln(Message3). start_communication :- message_queue_create(Queue), thread_create(producer(Queue), _, []), thread_create(consumer(Queue), _, []).
Resum
En aquesta secció, hem explorat els conceptes bàsics de la programació paral·lela i concurrent en Prolog. Hem après a crear i sincronitzar fils, així com a gestionar la comunicació entre ells. Aquests coneixements són fonamentals per desenvolupar aplicacions eficients i de rendiment elevat en Prolog. En el proper tema, ens endinsarem en la resolució de restriccions avançada.
Curs de Programació en Prolog
Mòdul 1: Introducció a Prolog
- Què és Prolog?
- Instal·lant Prolog
- Primers Passos en Prolog
- Sintaxi i Estructura Bàsiques
- Fets, Regles i Consultes
Mòdul 2: Programació Bàsica en Prolog
Mòdul 3: Estructures de Dades en Prolog
Mòdul 4: Programació Avançada en Prolog
- Unificació Avançada
- Tall i Negació
- Meta-Programació
- Gramàtiques de Claus Definides (DCGs)
- Programació Lògica amb Restriccions
Mòdul 5: Prolog en la Pràctica
- Entrada/Sortida de Fitxers
- Depuració de Programes Prolog
- Biblioteques Prolog
- Interfície amb Altres Llenguatges
- Construint una Aplicació Prolog