Introducción a Pthreads
Auxiliar de la palabra auxilio

Paralelismo en C
Procesos Pesados
Procesos livianos
int pthread_create(pthread_t *thread,
const pthread_attr_t *attr,
void *(*start_routine)(void *),
void *arg);Compuesto por:
int pthread_create(pthread_t *thread,
const pthread_attr_t *attr,
void *(*start_routine)(void *),
void *arg);Compuesto por:
int pthread_create(pthread_t *thread,
const pthread_attr_t *attr,
void *(*start_routine)(void *),
void *arg);Compuesto por:
NULL)int pthread_create(pthread_t *thread,
const pthread_attr_t *attr,
void *(*start_routine)(void *),
void *arg);Compuesto por:
NULL)int pthread_create(pthread_t *thread,
const pthread_attr_t *attr,
void *(*start_routine)(void *),
void *arg);Compuesto por:
NULL)int pthread_create(pthread_t *thread,
const pthread_attr_t *attr,
void *(*start_routine)(void *),
void *arg);Retorna 0 si la creación fue exitosa
El thread termina cuando start_routine termina
Todo thread creado debe ser enterrado con
Los thread no enterrados se convierte en zombies y no devuelven los recursos
La función pthread_join espera a que el thread termine
#include <stdio.h>
#include <pthread.h>
void *thread(void *ptr) {
char* nombre = (char*) ptr; // Castear argumento
printf("Thread - %s\n", nombre); // Trabajo en paralelo
return NULL; // Retorno
}
int main() {
pthread_t pid_1, pid_2; // Guardar PID de los threads lanzados
char* nombre_1 = "primero";
char* nombre_2 = "segundo";
pthread_create(&pid_1, NULL, thread, nombre_1); // lanzar thread1
pthread_create(&pid_2, NULL, thread, nombre_2); // lanzar thread2
pthread_join(pid_1, NULL); // esperar thread 1
pthread_join(pid_2, NULL); // esperar thread 2
return 0;
}¿Cómo puedo usar más argumentos?
Usamos una estructura!
#include <stdio.h>
#include <pthread.h>
typedef struct {
char* name;
int age;
} Args;
void *thread(void *ptr) {
char* nombre = (char*) ptr; // Castear argumento
printf("Thread - %s\n", nombre); // Trabajo en paralelo
return NULL; // Retorno
}
int main() {
pthread_t pid_1, pid_2; // Guardar PID de los threads lanzados
char* nombre_1 = "primero";
char* nombre_2 = "segundo";
pthread_create(&pid_1, NULL, thread, nombre_1); // lanzar thread1
pthread_create(&pid_2, NULL, thread, nombre_2); // lanzar thread2
pthread_join(pid_1, NULL); // esperar thread 1
pthread_join(pid_2, NULL); // esperar thread 2
return 0;
}#include <stdio.h>
#include <pthread.h>
typedef struct {
char* name;
int age;
} Args;
void *thread(void *ptr) {
char* nombre = (char*) ptr; // Castear argumento
printf("Thread - %s\n", nombre); // Trabajo en paralelo
return NULL; // Retorno
}
int main() {
pthread_t pid_1, pid_2; // Guardar PID de los threads lanzados
Args a1 = {"primero", 10} // inicializamos los args de t1
Args a2 = {"segundo", 20} // inicializamos los args de t2
pthread_create(&pid_1, NULL, thread, &a1); // la pasamos por referencia
pthread_create(&pid_2, NULL, thread, &a2); // la pasamos por referencia
pthread_join(pid_1, NULL); // esperar thread 1
pthread_join(pid_2, NULL); // esperar thread 2
return 0;
}#include <stdio.h>
#include <pthread.h>
typedef struct {
char* name;
int age;
} Args;
void *thread(void *ptr) {
Args* a = (Args*) ptr; // Castear a la estructura
printf("Thread - %s (%d)\n", a->name, a->age); // Accedemos a los miembros con ->
return NULL; // Retorno
}
int main() {
pthread_t pid_1, pid_2; // Guardar PID de los threads lanzados
Args a1 = {"primero", 10} // inicializamos los args de t1
Args a2 = {"segundo", 20} // inicializamos los args de t2
pthread_create(&pid_1, NULL, thread, &a1); // la pasamos por referencia
pthread_create(&pid_2, NULL, thread, &a2); // la pasamos por referencia
pthread_join(pid_1, NULL); // esperar thread 1
pthread_join(pid_2, NULL); // esperar thread 2
return 0;
}Esto es no pretende ser una receta, sino que una guía general
threads con sus argumentos correspondientesthread principaljoin no existe garantía de que el trabajo se haya terminadocreate y el joinEsto es no pretende ser una receta, sino que una guía general
Sólo uno realmente
Paralelicemos esta función que busca cualquier factor de un número para acelerarla utilizando \(P\) cores
Desafío: Lanzar \(P-1\) procesos y utilizar el principal en la búsqueda
¿Cómo harías para que todos los procesos terminen cuando se encuentre el primer factor?
#include <pthread.h>
typedef unsigned long long ulonglong;
typedef unsigned int uint;
// busca un factor del número entero x en el rango [i, j]
uint buscarFactor(ulonglong x, uint i, uint j){
for (uint k = i; k <= j; k++){
if (x % k == 0)
return k;
}
return 0;
}Hint: Quizás una variable global ayudaría
CC4302 — Sistemas Operativos