add files
This commit is contained in:
BIN
T1/.DS_Store
vendored
Normal file
BIN
T1/.DS_Store
vendored
Normal file
Binary file not shown.
84
T1/Makefile
Normal file
84
T1/Makefile
Normal file
@@ -0,0 +1,84 @@
|
||||
# Para revisar las opciones de compilacion y ejecucion,
|
||||
# ingrese en el terminal el comando: make
|
||||
#
|
||||
#
|
||||
|
||||
PROB=suma
|
||||
|
||||
TEST=test-$(PROB)
|
||||
HEADER=$(PROB)
|
||||
|
||||
SHELL=bash -o pipefail
|
||||
|
||||
INCLUDE=
|
||||
CFLAGS=-Wall -Werror -std=c18 $(INCLUDE)
|
||||
#CFLAGS=-Wall -Werror -pedantic -std=c18 $(INCLUDE)
|
||||
LDLIBS=-lm -lpthread
|
||||
|
||||
MAK=make --no-print-directory
|
||||
|
||||
readme:
|
||||
@less README.txt
|
||||
|
||||
$(PROB).bin $(PROB).bin-g $(PROB).bin-san $(PROB).bin-thr: $(PROB).c $(TEST).c $(HEADER).h
|
||||
|
||||
run-san: $(PROB).bin-san
|
||||
@if grep -P '\t' $(PROB).c ; then echo "Su archivo $(PROB).c contiene tabs. Reemplacelos por espacios en blanco!" ; false ; else true; fi
|
||||
./$(PROB).bin-san
|
||||
|
||||
run-thr: $(PROB).bin-thr
|
||||
./$(PROB).bin-thr
|
||||
|
||||
run-g: $(PROB).bin-g
|
||||
./$(PROB).bin-g
|
||||
|
||||
run: $(PROB).bin
|
||||
./$(PROB).bin
|
||||
|
||||
ddd: $(PROB).ddd
|
||||
|
||||
ddd-san: $(PROB).ddd-san
|
||||
|
||||
zip:
|
||||
@if grep -P '\t' $(PROB).c ; then echo "Su archivo $(PROB).c contiene tabs. Reemplacelos por espacios en blanco!" ; false ; else true; fi
|
||||
@rm -f resultados.txt $(PROB).zip
|
||||
@echo "Sistema operativo utilizado" > resultados.txt
|
||||
@uname -a >> resultados.txt
|
||||
@cat resultados.txt
|
||||
@echo ==== run-san ==== | tee -a resultados.txt
|
||||
@$(MAK) -B run-san | tee -a resultados.txt
|
||||
@echo ==== run-thr ==== | tee -a resultados.txt
|
||||
@$(MAK) -B run-thr | tee -a resultados.txt
|
||||
@echo ==== run-g ==== | tee -a resultados.txt
|
||||
@$(MAK) -B run-g | tee -a resultados.txt
|
||||
@echo ==== run ==== | tee -a resultados.txt
|
||||
@$(MAK) -B run | tee -a resultados.txt
|
||||
@echo ==== zip ====
|
||||
zip -r $(PROB).zip resultados.txt $(PROB).c
|
||||
@echo "Entregue por u-cursos el archivo $(PROB).zip"
|
||||
@echo "Descargue de u-cursos lo que entrego, descargue nuevamente los"
|
||||
@echo "archivos adjuntos y vuelva a probar la tarea tal cual como"
|
||||
@echo "la entrego. Esto es para evitar que Ud. reciba un 1.0 en su"
|
||||
@echo "tarea porque entrego los archivos equivocados. Creame, sucede"
|
||||
@echo "a menudo por ahorrarse esta verificacion."
|
||||
|
||||
%.bin: %.c
|
||||
gcc -O -DOPT=1 $(CFLAGS) $^ $(LDLIBS) -o $@
|
||||
|
||||
%.bin-g: %.c
|
||||
gcc -g $(CFLAGS) $^ $(LDLIBS) -o $@
|
||||
|
||||
%.bin-san: %.c
|
||||
gcc -g -DSAN=1 -fsanitize=address -fsanitize=undefined $(CFLAGS) $^ $(LDLIBS) -o $@
|
||||
|
||||
%.bin-thr: %.c
|
||||
gcc -g -DSAN=1 -fsanitize=thread -fsanitize=undefined $(CFLAGS) $^ $(LDLIBS) -o $@
|
||||
|
||||
%.ddd: %.bin-g
|
||||
ddd $(*F).bin-g &
|
||||
|
||||
%.ddd-san: %.bin-san
|
||||
ddd $(*F).bin-san &
|
||||
|
||||
clean:
|
||||
rm -f *.o *.log *.bin* core
|
||||
92
T1/README.txt
Normal file
92
T1/README.txt
Normal file
@@ -0,0 +1,92 @@
|
||||
==========================================================
|
||||
Esta es la documentación para compilar y ejecutar su tarea
|
||||
==========================================================
|
||||
|
||||
Se está ejecutando el comando: less README.txt
|
||||
|
||||
***************************
|
||||
*** Para salir: tecla q ***
|
||||
***************************
|
||||
|
||||
Para avanzar a una nueva página: tecla <page down>
|
||||
Para retroceder a la página anterior: tecla <page up>
|
||||
Para avanzar una sola línea: tecla <enter>
|
||||
Para buscar un texto: tecla / seguido del texto (/...texto...)
|
||||
por ejemplo: /ddd
|
||||
|
||||
-----------------------------------------------
|
||||
|
||||
Ud. debe crear el archivo suma.c y reprogramar ahí la función buscar.
|
||||
Ya hay una plantilla para suma.c en suma.c.plantilla.
|
||||
|
||||
Pruebe su tarea bajo Debian 13 de 64 bits. Estos son los requerimientos
|
||||
para aprobar su tarea:
|
||||
|
||||
+ make run-san debe felicitarlo y no reportar ningún incidente en el
|
||||
manejo de memoria.
|
||||
|
||||
+ make run-thr debe felicitarlo y no reportar ningún datarace
|
||||
|
||||
+ make run debe felicitarlo por aprobar este modo de ejecución.
|
||||
El speed up reportado debe ser de al menos 1.5.
|
||||
|
||||
+ make run-g debe felicitarlo.
|
||||
|
||||
Cuando pruebe su tarea con make run en su notebook asegúrese de que
|
||||
posea al menos 2 cores, que está configurado en modo alto rendimiento
|
||||
y que no estén corriendo otros procesos intensivos en uso de CPU al
|
||||
mismo tiempo. De otro modo podría no lograr el speed up solicitado.
|
||||
|
||||
Invoque el comando make zip para ejecutar todos los tests y generar un
|
||||
archivo suma.zip que contiene suma.c, con su solución, y resultados.txt,
|
||||
con la salida de make run, make run-g, make run-thr y make run-san.
|
||||
|
||||
Para depurar use: make ddd
|
||||
|
||||
Video con ejemplos de uso de ddd: https://youtu.be/FtHZy7UkTT4
|
||||
Archivos con los ejemplos: https://www.u-cursos.cl/ingenieria/2020/2/CC3301/1/novedades/r/demo-ddd.zip
|
||||
|
||||
-----------------------------------------------
|
||||
|
||||
Entrega de la tarea
|
||||
|
||||
Ejecute: make zip
|
||||
|
||||
Entregue por U-cursos el archivo suma.zip
|
||||
|
||||
A continuación es muy importante que descargue de U-cursos el mismo
|
||||
archivo que subió, luego descargue nuevamente los archivos adjuntos y
|
||||
vuelva a probar la tarea tal cual como la entregó. Esto es para
|
||||
evitar que Ud. reciba un 1.0 en su tarea porque entregó los archivos
|
||||
equivocados. Creame, sucede a menudo por ahorrarse esta verificación.
|
||||
|
||||
-----------------------------------------------
|
||||
|
||||
Limpieza de archivos
|
||||
|
||||
make clean
|
||||
|
||||
Hace limpieza borrando todos los archivos que se pueden volver
|
||||
a reconstruir a partir de los fuentes: *.o binarios etc.
|
||||
|
||||
-----------------------------------------------
|
||||
|
||||
Acerca del comando make
|
||||
|
||||
El comando make sirve para automatizar el proceso de compilación asegurando
|
||||
recompilar el archivo binario ejecutable cuando cambió uno de los archivos
|
||||
fuentes de los cuales depende.
|
||||
|
||||
A veces es útil usar make con la opción -n para que solo muestre
|
||||
exactamente qué comandos va a ejecutar, sin ejecutarlos de verdad.
|
||||
Por ejemplo:
|
||||
|
||||
make -n sort-rv-nbits.ddd
|
||||
|
||||
También es útil usar make con la opción -B para forzar la recompilación
|
||||
de los fuentes a pesar de que no han cambiado desde la última compilación.
|
||||
Por ejemplo:
|
||||
|
||||
make -B sort-rv-nbits
|
||||
|
||||
Recompilará para generar el archivo sort-rv-nbits desde cero
|
||||
90
T1/suma.c
Normal file
90
T1/suma.c
Normal file
@@ -0,0 +1,90 @@
|
||||
#include <limits.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#include "suma.h"
|
||||
|
||||
enum { NTHREADS = 8 };
|
||||
|
||||
typedef struct {
|
||||
int *a;
|
||||
int n;
|
||||
Set start;
|
||||
Set end;
|
||||
Set found;
|
||||
} BuscarArgs;
|
||||
|
||||
static Set total_combinaciones(int n) {
|
||||
if (n >= (int)(sizeof(Set) * CHAR_BIT))
|
||||
return ~(Set)0;
|
||||
return ((Set)1 << n) - 1;
|
||||
}
|
||||
|
||||
static Set buscar_rango(int a[], int n, Set start, Set end) {
|
||||
if (start == 0 || start > end)
|
||||
return 0;
|
||||
|
||||
Set k = start;
|
||||
while (1) {
|
||||
long long sum = 0;
|
||||
|
||||
for (int i = 0; i < n; i++) {
|
||||
if (k & ((Set)1 << i))
|
||||
sum += a[i];
|
||||
}
|
||||
|
||||
if (sum == 0)
|
||||
return k;
|
||||
|
||||
if (k == end)
|
||||
break;
|
||||
k++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void *buscar_thread(void *ptr) {
|
||||
BuscarArgs *args = ptr;
|
||||
args->found = buscar_rango(args->a, args->n, args->start, args->end);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Set buscar(int a[], int n) {
|
||||
Set comb = total_combinaciones(n);
|
||||
Set base = comb / NTHREADS;
|
||||
Set extra = comb % NTHREADS;
|
||||
Set next = 1;
|
||||
pthread_t tids[NTHREADS];
|
||||
BuscarArgs args[NTHREADS];
|
||||
int created = 0;
|
||||
|
||||
for (int t = 0; t < NTHREADS; t++) {
|
||||
Set len = base + (Set)(t < (int)extra);
|
||||
|
||||
args[t].a = a;
|
||||
args[t].n = n;
|
||||
args[t].start = next;
|
||||
args[t].end = (len == 0) ? next - 1
|
||||
: (t == NTHREADS - 1 ? comb : next + len - 1);
|
||||
args[t].found = 0;
|
||||
|
||||
if (len != 0)
|
||||
next = args[t].end + 1;
|
||||
|
||||
if (pthread_create(&tids[t], NULL, buscar_thread, &args[t]) != 0) {
|
||||
for (int i = 0; i < created; i++)
|
||||
pthread_join(tids[i], NULL);
|
||||
return buscar_rango(a, n, 1, comb);
|
||||
}
|
||||
created++;
|
||||
}
|
||||
|
||||
Set best = 0;
|
||||
for (int t = 0; t < NTHREADS; t++) {
|
||||
pthread_join(tids[t], NULL);
|
||||
if (args[t].found != 0 && (best == 0 || args[t].found < best))
|
||||
best = args[t].found;
|
||||
}
|
||||
|
||||
return best;
|
||||
}
|
||||
15
T1/suma.c.plantilla
Normal file
15
T1/suma.c.plantilla
Normal file
@@ -0,0 +1,15 @@
|
||||
#include <pthread.h>
|
||||
#include "suma.h"
|
||||
|
||||
// Defina aca las estructuras que necesite
|
||||
|
||||
... complete ...
|
||||
|
||||
// Defina aca la funcion que ejecutaran los threads
|
||||
|
||||
... complete ...
|
||||
|
||||
// Reprograme aca la funcion buscar
|
||||
Set buscar(int a[], int n) {
|
||||
... complete ...
|
||||
}
|
||||
4
T1/suma.h
Normal file
4
T1/suma.h
Normal file
@@ -0,0 +1,4 @@
|
||||
typedef unsigned long long Set;
|
||||
|
||||
Set buscar(int a[], int n);
|
||||
|
||||
BIN
T1/suma.manual.bin
Executable file
BIN
T1/suma.manual.bin
Executable file
Binary file not shown.
BIN
T1/suma.manual.san
Executable file
BIN
T1/suma.manual.san
Executable file
Binary file not shown.
20
T1/suma.manual.san.dSYM/Contents/Info.plist
Normal file
20
T1/suma.manual.san.dSYM/Contents/Info.plist
Normal file
@@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>English</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>com.apple.xcode.dsym.suma.manual.san</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>dSYM</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1</string>
|
||||
</dict>
|
||||
</plist>
|
||||
BIN
T1/suma.manual.san.dSYM/Contents/Resources/DWARF/suma.manual.san
Normal file
BIN
T1/suma.manual.san.dSYM/Contents/Resources/DWARF/suma.manual.san
Normal file
Binary file not shown.
@@ -0,0 +1,5 @@
|
||||
---
|
||||
triple: 'arm64-apple-darwin'
|
||||
binary-path: suma.manual.san
|
||||
relocations: []
|
||||
...
|
||||
BIN
T1/suma.manual.thr
Executable file
BIN
T1/suma.manual.thr
Executable file
Binary file not shown.
20
T1/suma.manual.thr.dSYM/Contents/Info.plist
Normal file
20
T1/suma.manual.thr.dSYM/Contents/Info.plist
Normal file
@@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>English</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>com.apple.xcode.dsym.suma.manual.thr</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>dSYM</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1</string>
|
||||
</dict>
|
||||
</plist>
|
||||
BIN
T1/suma.manual.thr.dSYM/Contents/Resources/DWARF/suma.manual.thr
Normal file
BIN
T1/suma.manual.thr.dSYM/Contents/Resources/DWARF/suma.manual.thr
Normal file
Binary file not shown.
@@ -0,0 +1,5 @@
|
||||
---
|
||||
triple: 'arm64-apple-darwin'
|
||||
binary-path: suma.manual.thr
|
||||
relocations: []
|
||||
...
|
||||
176
T1/test-suma.c
Normal file
176
T1/test-suma.c
Normal file
@@ -0,0 +1,176 @@
|
||||
#include <stdio.h>
|
||||
#include <pthread.h>
|
||||
#include <math.h>
|
||||
#include <sys/time.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "suma.h"
|
||||
|
||||
#ifdef OPT
|
||||
#define N_INTENTOS 4
|
||||
#define TOLERANCIA 1.5
|
||||
#else
|
||||
#define N_INTENTOS 1
|
||||
#define TOLERANCIA 0.01
|
||||
#endif
|
||||
|
||||
|
||||
// ----------------------------------------------------
|
||||
// Funcion que entrega el tiempo transcurrido desde el lanzamiento del
|
||||
// programa en milisegundos
|
||||
|
||||
static int time0= 0;
|
||||
|
||||
static int getTime0() {
|
||||
struct timeval Timeval;
|
||||
gettimeofday(&Timeval, NULL);
|
||||
return Timeval.tv_sec*1000+Timeval.tv_usec/1000;
|
||||
}
|
||||
|
||||
void resetTime() {
|
||||
time0= getTime0();
|
||||
}
|
||||
|
||||
int getTime() {
|
||||
return getTime0()-time0;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------
|
||||
|
||||
Set buscarSeq(int a[], int n) {
|
||||
Set comb= (1<<(n-1)<<1)-1; // 2n-1: nro. de combinaciones
|
||||
for (Set k= 1; k<=comb; k++) {
|
||||
// k es el mapa de bits para el subconjunto { a[i] | bit ki de k es 1 }
|
||||
long long sum= 0;
|
||||
for (int i= 0; i<n; i++) {
|
||||
if ( k & ((Set)1<<i) ) // si bit ki de k es 1
|
||||
sum+= a[i];
|
||||
}
|
||||
if (sum==0) { // exito: el subconjunto suma 0
|
||||
return k; // y el mapa de bits para el subconjunto es k
|
||||
} }
|
||||
return 0; // no existe subconjunto que sume 0
|
||||
}
|
||||
|
||||
void mostrar(int a[], Set k, int n) {
|
||||
long long sum= 0;
|
||||
if (k==0) {
|
||||
printf("subconjunto no existe\n");
|
||||
return;
|
||||
}
|
||||
for (int i= 0; i<n; i++) {
|
||||
if ( k & ((Set)1<<i) ) {
|
||||
printf("%d ", a[i]);
|
||||
sum+= a[i];
|
||||
}
|
||||
}
|
||||
if (sum!=0) {
|
||||
fprintf(stderr, "El subconjunto suma %lld, no 0\n", sum);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
#define N 10000
|
||||
#define M 20000
|
||||
#define P 4
|
||||
|
||||
int main() {
|
||||
|
||||
printf("Test 1: El ejemplo del enunciado\n");
|
||||
int a[]= { -7, -3, -2, 5, 8};
|
||||
Set kSeq= buscarSeq(a, 5);
|
||||
mostrar(a, kSeq, 5);
|
||||
Set k= buscar(a, 5);
|
||||
if (k!=kSeq) {
|
||||
fprintf(stderr, "La solucion debio ser %lld, no %lld\n", kSeq, k);
|
||||
exit(1);
|
||||
}
|
||||
mostrar(a, k, 5);
|
||||
printf("test 1 aprobado\n");
|
||||
printf("\n--------------------------------------------------\n\n");
|
||||
|
||||
printf("Test 2: Uno ejemplo mas grande con n=26, sin solucion\n");
|
||||
int b[]= { 122737, -37364, 287373, -27267, 967923, -25383, 924973, -28973,
|
||||
278363, 28272, 98734, -26735, -983267, 674998, 72537, 116725,
|
||||
72537, 27263, 82739, 829276, -5383715, 675483, -28334, 38495,
|
||||
374943, 278367};
|
||||
|
||||
int tiempo_sec, tiempo_par;
|
||||
double speedUp= 0;
|
||||
int i;
|
||||
|
||||
printf("Calculando secuencialmente 2 veces\n");
|
||||
for (i= 0; i<2; i++) {
|
||||
resetTime();
|
||||
k= buscarSeq(b, 26);
|
||||
if (k!=0) {
|
||||
mostrar(b, k, 26);
|
||||
fprintf(stderr, "Bug del profesor: la solucion debio ser %d, no %lld\n",
|
||||
0, k);
|
||||
exit(1);
|
||||
}
|
||||
tiempo_sec= getTime();
|
||||
printf("Tiempo secuencial= %d milisegundos\n", tiempo_sec);
|
||||
}
|
||||
|
||||
printf("Calculando en paralelo hasta 5 veces\n");
|
||||
for (i= 0; i<N_INTENTOS; i++) {
|
||||
resetTime();
|
||||
k= buscar(b, 26);
|
||||
if (k!=0) {
|
||||
mostrar(b, k, 26);
|
||||
fprintf(stderr, "La solucion debio ser %d, no %lld\n", 0, k);
|
||||
exit(1);
|
||||
}
|
||||
tiempo_par= getTime();
|
||||
speedUp= (double)tiempo_sec/tiempo_par;
|
||||
printf("buscar par tiempo= %d miliseg., speedup= %f\n", tiempo_par, speedUp);
|
||||
if (speedUp>=TOLERANCIA)
|
||||
break;
|
||||
}
|
||||
if (i>=N_INTENTOS) {
|
||||
fprintf(stderr, "Despues de %d intentos no obtuvo un speedup de %f\n",
|
||||
N_INTENTOS, TOLERANCIA);
|
||||
fprintf(stderr, "Revise la paralelizacion.\n");
|
||||
exit(1);
|
||||
}
|
||||
printf("test 1 aprobado: speedup >= %f\n", TOLERANCIA);
|
||||
printf("\n--------------------------------------------------\n\n");
|
||||
|
||||
printf("Uno ejemplo muy grande con n=29, con solucion\n");
|
||||
int c[]= { -3, -2, 5,
|
||||
122737, -37364, 287373, 27267, 967923, -25383, 924973, -28973,
|
||||
278363, 28272, 98734, -26735, 983267, 674998, 72537, 116725,
|
||||
72537, 27263, 82739, 829276, 5383715, 675483, -28334, 38495,
|
||||
374943, 278367};
|
||||
|
||||
printf("Calculando secuencialmente 2 veces\n");
|
||||
resetTime();
|
||||
k= buscarSeq(c, 29);
|
||||
tiempo_sec= getTime();
|
||||
mostrar(c, k, 29);
|
||||
printf("Tiempo secuencial= %d milisegundos\n", tiempo_sec);
|
||||
|
||||
printf("Calculando en paralelo\n");
|
||||
resetTime();
|
||||
int k29= buscar(c, 29);
|
||||
if (k!=k29) {
|
||||
printf("Solucion incorrecta:\n");
|
||||
mostrar(c, k29, 29);
|
||||
printf("Debio ser:\n");
|
||||
mostrar(c, k, 29);
|
||||
exit(1);
|
||||
}
|
||||
tiempo_par= getTime();
|
||||
speedUp= (double)tiempo_sec/tiempo_par;
|
||||
printf("buscar par tiempo= %d miliseg., speedup= %f\n", tiempo_par, speedUp);
|
||||
printf("No se preocupe. Es normal que la version paralela se demore\n"
|
||||
"mucho mas. Pero piense por que.\n\n");
|
||||
|
||||
printf("Felicitaciones: su tarea funciona\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user