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
