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

  1. 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.

  1. 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

  1. 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.

  1. 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).

  1. 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)), _, []).

  1. 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.

© Copyright 2024. Tots els drets reservats