Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
Iker Martín Álvarez
Malleable_CG
Commits
95f9a9a6
Commit
95f9a9a6
authored
Sep 19, 2023
by
iker_martin
Browse files
First commit
parent
8dc4bd2b
Changes
33
Show whitespace changes
Inline
Side-by-side
malleability/malleabilityZombies.c
0 → 100644
View file @
95f9a9a6
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <mpi.h>
#include <signal.h>
#include "malleabilityZombies.h"
#define PIDS_QTY 320
void
zombies_suspend
();
int
offset_pids
,
*
pids
=
NULL
;
void
gestor_usr2
()
{}
void
zombies_collect_suspended
(
MPI_Comm
comm
,
int
myId
,
int
numP
,
int
numC
,
int
root
)
{
int
pid
=
getpid
();
int
*
pids_counts
=
malloc
(
numP
*
sizeof
(
int
));
int
*
pids_displs
=
malloc
(
numP
*
sizeof
(
int
));
int
i
,
count
=
1
;
if
(
myId
<
numC
)
{
count
=
0
;
if
(
myId
==
root
)
{
for
(
i
=
0
;
i
<
numC
;
i
++
)
{
pids_counts
[
i
]
=
0
;
}
for
(
i
=
numC
;
i
<
numP
;
i
++
)
{
pids_counts
[
i
]
=
1
;
pids_displs
[
i
]
=
(
i
+
offset_pids
)
-
numC
;
}
offset_pids
+=
numP
-
numC
;
}
}
MPI_Gatherv
(
&
pid
,
count
,
MPI_INT
,
pids
,
pids_counts
,
pids_displs
,
MPI_INT
,
root
,
comm
);
free
(
pids_counts
);
free
(
pids_displs
);
if
(
myId
>=
numC
)
{
zombies_suspend
();
}
}
void
zombies_service_init
()
{
offset_pids
=
0
;
pids
=
malloc
(
PIDS_QTY
*
sizeof
(
int
));
for
(
int
i
=
0
;
i
<
PIDS_QTY
;
i
++
)
{
pids
[
i
]
=
0
;
}
}
void
zombies_service_free
()
{
free
(
pids
);
}
void
zombies_suspend
()
{
struct
sigaction
act
;
sigemptyset
(
&
act
.
sa_mask
);
act
.
sa_flags
=
0
;
act
.
sa_handler
=
gestor_usr2
;
sigaction
(
SIGUSR2
,
&
act
,
NULL
);
sigset_t
set
;
sigprocmask
(
SIG_SETMASK
,
NULL
,
&
set
);
sigsuspend
(
&
set
);
}
void
zombies_awake
()
{
for
(
int
i
=
0
;
i
<
offset_pids
;
i
++
)
{
// Despertar a los zombies
kill
(
pids
[
i
],
SIGUSR2
);
}
}
malleability/malleabilityZombies.h
0 → 100644
View file @
95f9a9a6
#ifndef MALLEABILITY_ZOMBIES_H
#define MALLEABILITY_ZOMBIES_H
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <mpi.h>
#include <signal.h>
void
zombies_collect_suspended
(
MPI_Comm
comm
,
int
myId
,
int
numP
,
int
numC
,
int
root
);
void
zombies_service_init
();
void
zombies_service_free
();
void
zombies_awake
();
#endif
malleability/spawn_methods/Baseline.c
0 → 100644
View file @
95f9a9a6
#include <stdio.h>
#include <stdlib.h>
#include <mpi.h>
#include "../malleabilityStates.h"
#include "Baseline.h"
#include "Spawn_state.h"
//--------------PRIVATE DECLARATIONS---------------//
int
baseline_spawn
(
Spawn_data
spawn_data
,
MPI_Comm
comm
,
MPI_Comm
*
child
);
int
single_strat_parents
(
Spawn_data
spawn_data
,
MPI_Comm
*
child
);
void
single_strat_children
(
int
myId
,
int
root
,
MPI_Comm
*
parents
);
//--------------PUBLIC FUNCTIONS---------------//
/*
* Metodo basico para la creacion de procesos. Crea en total
* spawn_data.spawn_qty procesos.
*/
int
baseline
(
Spawn_data
spawn_data
,
MPI_Comm
*
child
)
{
//TODO Tratamiento de errores
MPI_Comm
intercomm
;
MPI_Comm_get_parent
(
&
intercomm
);
if
(
intercomm
==
MPI_COMM_NULL
)
{
// Parents path
if
(
spawn_data
.
spawn_is_single
)
{
single_strat_parents
(
spawn_data
,
child
);
}
else
{
baseline_spawn
(
spawn_data
,
spawn_data
.
comm
,
child
);
}
}
else
if
(
spawn_data
.
spawn_is_single
)
{
// Children path
single_strat_children
(
spawn_data
.
myId
,
spawn_data
.
root
,
child
);
}
return
MALL_SPAWN_COMPLETED
;
}
//--------------PRIVATE FUNCTIONS---------------//
/*
* Crea un grupo de procesos segun la configuracion indicada por la funcion
* "processes_dist()".
*/
int
baseline_spawn
(
Spawn_data
spawn_data
,
MPI_Comm
comm
,
MPI_Comm
*
child
)
{
int
rootBcast
=
MPI_PROC_NULL
;
if
(
spawn_data
.
myId
==
spawn_data
.
root
)
rootBcast
=
MPI_ROOT
;
// WORK
int
spawn_err
=
MPI_Comm_spawn
(
spawn_data
.
cmd
,
MPI_ARGV_NULL
,
spawn_data
.
spawn_qty
,
spawn_data
.
mapping
,
spawn_data
.
root
,
comm
,
child
,
MPI_ERRCODES_IGNORE
);
MPI_Comm_set_name
(
*
child
,
"MPI_COMM_MALL_RESIZE"
);
// END WORK
if
(
spawn_err
!=
MPI_SUCCESS
)
{
printf
(
"Error creating new set of %d procs.
\n
"
,
spawn_data
.
spawn_qty
);
}
MPI_Bcast
(
&
spawn_data
,
1
,
spawn_data
.
dtype
,
rootBcast
,
*
child
);
return
spawn_err
;
}
/*
* Si la variable "type" es 1, la creación es con la participación de todo el grupo de padres
* Si el valor es diferente, la creación es solo con la participación del proceso root
*/
int
single_strat_parents
(
Spawn_data
spawn_data
,
MPI_Comm
*
child
)
{
int
spawn_err
;
char
*
port_name
;
MPI_Comm
newintercomm
;
if
(
spawn_data
.
myId
==
spawn_data
.
root
)
{
spawn_err
=
baseline_spawn
(
spawn_data
,
MPI_COMM_SELF
,
child
);
port_name
=
(
char
*
)
malloc
(
MPI_MAX_PORT_NAME
*
sizeof
(
char
));
MPI_Recv
(
port_name
,
MPI_MAX_PORT_NAME
,
MPI_CHAR
,
spawn_data
.
root
,
130
,
*
child
,
MPI_STATUS_IGNORE
);
set_spawn_state
(
MALL_SPAWN_SINGLE_COMPLETED
,
spawn_data
.
spawn_is_async
);
// Indicate other processes to join root to end spawn procedure
}
else
{
port_name
=
malloc
(
1
);
}
MPI_Comm_connect
(
port_name
,
MPI_INFO_NULL
,
spawn_data
.
root
,
spawn_data
.
comm
,
&
newintercomm
);
if
(
spawn_data
.
myId
==
spawn_data
.
root
)
MPI_Comm_free
(
child
);
free
(
port_name
);
*
child
=
newintercomm
;
return
spawn_err
;
}
/*
* Conectar grupo de hijos con grupo de padres
* Devuelve un intercomunicador para hablar con los padres
*
* Solo se utiliza cuando la creación de los procesos ha sido
* realizada por un solo proceso padre
*/
void
single_strat_children
(
int
myId
,
int
root
,
MPI_Comm
*
parents
)
{
char
*
port_name
;
MPI_Comm
newintercomm
;
if
(
myId
==
root
)
{
port_name
=
(
char
*
)
malloc
(
MPI_MAX_PORT_NAME
*
sizeof
(
char
));
MPI_Open_port
(
MPI_INFO_NULL
,
port_name
);
MPI_Send
(
port_name
,
MPI_MAX_PORT_NAME
,
MPI_CHAR
,
root
,
130
,
*
parents
);
}
else
{
port_name
=
malloc
(
1
);
}
MPI_Comm_accept
(
port_name
,
MPI_INFO_NULL
,
root
,
MPI_COMM_WORLD
,
&
newintercomm
);
if
(
myId
==
root
)
{
MPI_Close_port
(
port_name
);
}
free
(
port_name
);
MPI_Comm_free
(
parents
);
*
parents
=
newintercomm
;
}
malleability/spawn_methods/Baseline.h
0 → 100644
View file @
95f9a9a6
#ifndef MALLEABILITY_SPAWN_BASELINE_H
#define MALLEABILITY_SPAWN_BASELINE_H
#include <stdio.h>
#include <stdlib.h>
#include <mpi.h>
#include <string.h>
#include "../malleabilityDataStructures.h"
int
baseline
(
Spawn_data
spawn_data
,
MPI_Comm
*
child
);
#endif
malleability/spawn_methods/GenericSpawn.c
0 → 100644
View file @
95f9a9a6
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <pthread.h>
#include <mpi.h>
#include <string.h>
#include "../malleabilityStates.h"
#include "ProcessDist.h"
#include "GenericSpawn.h"
#include "Baseline.h"
#include "Merge.h"
#include "Spawn_state.h"
// This code is a Singleton object -- Only one instance can be used at a given time and
// no multiple calls to perform diferent resizes can be performed at the same time.
Spawn_data
*
spawn_data
=
NULL
;
pthread_t
spawn_thread
;
MPI_Comm
*
returned_comm
;
double
end_time
;
//FIXME REFACTOR
//--------------PRIVATE CONFIGURATION DECLARATIONS---------------//
void
set_spawn_configuration
(
char
*
cmd
,
int
num_cpus
,
int
num_nodes
,
char
*
nodelist
,
int
myId
,
int
root
,
int
initial_qty
,
int
target_qty
,
int
type_dist
,
int
spawn_method
,
int
spawn_strategies
,
MPI_Comm
comm
);
void
set_basic_spawn_dtype
();
void
deallocate_spawn_data
();
//--------------PRIVATE DECLARATIONS---------------//
void
generic_spawn
(
MPI_Comm
*
child
,
int
data_stage
);
int
check_single_state
(
MPI_Comm
comm
,
int
global_state
);
int
check_generic_state
(
MPI_Comm
comm
,
MPI_Comm
*
child
,
int
local_state
,
double
*
real_time
);
//--------------PRIVATE THREADS DECLARATIONS---------------//
int
allocate_thread_spawn
();
void
*
thread_work
();
//--------------PUBLIC FUNCTIONS---------------//
/*
* Se solicita la creacion de un nuevo grupo de "numP" procesos con una distribucion
* fisica "type_dist".
*
* Se puede solicitar en primer plano, encargandose por tanto el proceso que llama a esta funcion,
* o en segundo plano, donde un hilo se encarga de configurar esta creacion.
*
* Si se pide en primer plano, al terminarla es posible llamar a "check_spawn_state()" para crear
* los procesos.
*
* Si se pide en segundo plano, llamar a "check_spawn_state()" comprobara si la configuracion para
* crearlos esta lista, y si es asi, los crea.
*
* Devuelve el estado de el procedimiento. Si no devuelve "MALL_SPAWN_COMPLETED", es necesario llamar a
* "check_spawn_state()".
*/
int
init_spawn
(
char
*
argv
,
int
num_cpus
,
int
num_nodes
,
char
*
nodelist
,
int
myId
,
int
initial_qty
,
int
target_qty
,
int
root
,
int
type_dist
,
int
spawn_method
,
int
spawn_strategies
,
MPI_Comm
comm
,
MPI_Comm
*
child
)
{
int
local_state
;
set_spawn_configuration
(
argv
,
num_cpus
,
num_nodes
,
nodelist
,
myId
,
root
,
initial_qty
,
target_qty
,
type_dist
,
spawn_method
,
spawn_strategies
,
comm
);
if
(
!
spawn_data
->
spawn_is_async
)
{
generic_spawn
(
child
,
MALL_NOT_STARTED
);
local_state
=
get_spawn_state
(
spawn_data
->
spawn_is_async
);
if
(
local_state
==
MALL_SPAWN_COMPLETED
)
deallocate_spawn_data
();
}
else
{
local_state
=
spawn_data
->
spawn_is_single
?
MALL_SPAWN_SINGLE_PENDING
:
MALL_SPAWN_PENDING
;
local_state
=
spawn_data
->
spawn_method
==
MALL_SPAWN_MERGE
&&
spawn_data
->
initial_qty
>
spawn_data
->
target_qty
?
MALL_SPAWN_ADAPT_POSTPONE
:
local_state
;
set_spawn_state
(
local_state
,
0
);
if
((
spawn_data
->
spawn_is_single
&&
myId
==
root
)
||
!
spawn_data
->
spawn_is_single
)
{
allocate_thread_spawn
();
}
}
return
local_state
;
}
/*
* Comprueba si una configuracion para crear un nuevo grupo de procesos esta lista,
* y en caso de que lo este, se devuelve el communicador a estos nuevos procesos.
*/
int
check_spawn_state
(
MPI_Comm
*
child
,
MPI_Comm
comm
,
double
*
real_time
)
{
int
local_state
;
int
global_state
=
MALL_NOT_STARTED
;
if
(
spawn_data
->
spawn_is_async
)
{
// Async
local_state
=
get_spawn_state
(
spawn_data
->
spawn_is_async
);
if
(
local_state
==
MALL_SPAWN_SINGLE_PENDING
||
local_state
==
MALL_SPAWN_SINGLE_COMPLETED
)
{
// Single
global_state
=
check_single_state
(
comm
,
local_state
);
}
else
if
(
local_state
==
MALL_SPAWN_PENDING
||
local_state
==
MALL_SPAWN_COMPLETED
||
local_state
==
MALL_SPAWN_ADAPTED
)
{
// Baseline
global_state
=
check_generic_state
(
comm
,
child
,
local_state
,
real_time
);
}
else
if
(
local_state
==
MALL_SPAWN_ADAPT_POSTPONE
)
{
global_state
=
local_state
;
}
else
{
printf
(
"Error Check spawn: Configuracion invalida State = %d
\n
"
,
local_state
);
MPI_Abort
(
MPI_COMM_WORLD
,
-
1
);
return
-
10
;
}
}
else
if
(
spawn_data
->
spawn_method
==
MALL_SPAWN_MERGE
){
// Start Merge shrink Sync
generic_spawn
(
child
,
MALL_DIST_COMPLETED
);
global_state
=
get_spawn_state
(
spawn_data
->
spawn_is_async
);
}
if
(
global_state
==
MALL_SPAWN_COMPLETED
||
global_state
==
MALL_SPAWN_ADAPTED
)
deallocate_spawn_data
();
return
global_state
;
}
/*
* Elimina la bandera bloqueante MALL_SPAWN_ADAPT_POSTPONE para los hilos
* auxiliares. Esta bandera los bloquea para que el metodo Merge shrink no
* avance hasta que se complete la redistribucion de datos. Por tanto,
* al modificar la bandera los hilos pueden continuar.
*
* Por seguridad se comprueba que no se realice el cambio a la bandera a
* no ser que se cumplan las 3 condiciones.
*/
void
unset_spawn_postpone_flag
(
int
outside_state
)
{
int
local_state
=
get_spawn_state
(
spawn_data
->
spawn_is_async
);
if
(
local_state
==
MALL_SPAWN_ADAPT_POSTPONE
&&
outside_state
==
MALL_SPAWN_ADAPT_PENDING
&&
spawn_data
->
spawn_is_async
)
{
set_spawn_state
(
MALL_SPAWN_PENDING
,
MALL_SPAWN_PTHREAD
);
wakeup
();
}
}
/*
* Funcion bloqueante de los hijos para asegurar que todas las tareas del paso
* de creacion de los hijos se terminan correctamente.
*
* Ademas los hijos obtienen informacion basica de los padres
* para el paso de redistribucion de datos (Numeros de procesos y Id del Root).
*
*/
void
malleability_connect_children
(
int
myId
,
int
numP
,
int
root
,
MPI_Comm
comm
,
int
*
numP_parents
,
int
*
root_parents
,
MPI_Comm
*
parents
)
{
spawn_data
=
(
Spawn_data
*
)
malloc
(
sizeof
(
Spawn_data
));
spawn_data
->
root
=
root
;
spawn_data
->
myId
=
myId
;
spawn_data
->
spawn_qty
=
numP
;
spawn_data
->
target_qty
=
numP
;
spawn_data
->
comm
=
comm
;
set_basic_spawn_dtype
();
MPI_Bcast
(
spawn_data
,
1
,
spawn_data
->
dtype
,
MALLEABILITY_ROOT
,
*
parents
);
switch
(
spawn_data
->
spawn_method
)
{
case
MALL_SPAWN_BASELINE
:
baseline
(
*
spawn_data
,
parents
);
break
;
case
MALL_SPAWN_MERGE
:
spawn_data
->
target_qty
+=
spawn_data
->
initial_qty
;
merge
(
*
spawn_data
,
parents
,
MALL_NOT_STARTED
);
break
;
}
*
root_parents
=
spawn_data
->
root_parents
;
*
numP_parents
=
spawn_data
->
initial_qty
;
MPI_Type_free
(
&
(
spawn_data
->
dtype
));
free
(
spawn_data
);
}
/*
* Función para obtener si entre las estrategias elegidas, se utiliza
* la estrategia pasada como segundo argumento.
*
* Devuelve en "result" 1(Verdadero) si utiliza la estrategia, 0(Falso) en caso
* contrario.
*/
int
malleability_spawn_contains_strat
(
int
spawn_strategies
,
int
strategy
,
int
*
result
)
{
int
value
=
spawn_strategies
%
strategy
?
0
:
1
;
if
(
result
!=
NULL
)
*
result
=
value
;
return
value
;
}
//--------------PRIVATE CONFIGURATION FUNCTIONS---------------//
/*
* Agrupa en una sola estructura todos los datos de configuración necesarios
* e inicializa las estructuras necesarias.
*/
void
set_spawn_configuration
(
char
*
cmd
,
int
num_cpus
,
int
num_nodes
,
char
*
nodelist
,
int
myId
,
int
root
,
int
initial_qty
,
int
target_qty
,
int
type_dist
,
int
spawn_method
,
int
spawn_strategies
,
MPI_Comm
comm
)
{
spawn_data
=
(
Spawn_data
*
)
malloc
(
sizeof
(
Spawn_data
));
spawn_data
->
myId
=
myId
;
spawn_data
->
root
=
root
;
spawn_data
->
root_parents
=
root
;
spawn_data
->
initial_qty
=
initial_qty
;
spawn_data
->
target_qty
=
target_qty
;
spawn_data
->
spawn_method
=
spawn_method
;
malleability_spawn_contains_strat
(
spawn_strategies
,
MALL_SPAWN_SINGLE
,
&
(
spawn_data
->
spawn_is_single
));
malleability_spawn_contains_strat
(
spawn_strategies
,
MALL_SPAWN_PTHREAD
,
&
(
spawn_data
->
spawn_is_async
));
spawn_data
->
comm
=
comm
;
set_basic_spawn_dtype
();
switch
(
spawn_data
->
spawn_method
)
{
case
MALL_SPAWN_BASELINE
:
spawn_data
->
spawn_qty
=
spawn_data
->
target_qty
;
spawn_data
->
already_created
=
0
;
break
;
case
MALL_SPAWN_MERGE
:
spawn_data
->
spawn_qty
=
spawn_data
->
target_qty
-
spawn_data
->
initial_qty
;
spawn_data
->
already_created
=
spawn_data
->
initial_qty
;
break
;
}
if
(
spawn_data
->
spawn_is_async
)
{
init_spawn_state
();
}
spawn_data
->
mapping
=
MPI_INFO_NULL
;
if
(
spawn_data
->
myId
==
spawn_data
->
root
)
{
physical_struct_create
(
target_qty
,
spawn_data
->
already_created
,
num_cpus
,
num_nodes
,
nodelist
,
type_dist
,
MALL_DIST_STRING
,
&
(
spawn_data
->
dist
));
//COPY PROGRAM NAME
spawn_data
->
cmd
=
malloc
((
strlen
(
cmd
)
+
1
)
*
sizeof
(
char
));
strcpy
(
spawn_data
->
cmd
,
cmd
);
spawn_data
->
cmd
[
strlen
(
cmd
)]
=
'\0'
;
}
else
{
spawn_data
->
cmd
=
malloc
(
1
*
sizeof
(
char
));
}
}
/*
* Crea un tipo derivado para mandar 4 enteros con informacion
* basica a los hijos. Son datos necesarios para que terminen
* la creacion de procesos.
*/
void
set_basic_spawn_dtype
()
{
int
i
,
counts
=
4
;
int
blocklengths
[]
=
{
1
,
1
,
1
,
1
};
MPI_Aint
displs
[
counts
],
dir
;
MPI_Datatype
types
[
counts
];
// Rellenar vector types
types
[
0
]
=
types
[
1
]
=
types
[
2
]
=
types
[
3
]
=
MPI_INT
;
// Rellenar vector displs
MPI_Get_address
(
spawn_data
,
&
dir
);
MPI_Get_address
(
&
(
spawn_data
->
root_parents
),
&
displs
[
0
]);
MPI_Get_address
(
&
(
spawn_data
->
initial_qty
),
&
displs
[
1
]);
MPI_Get_address
(
&
(
spawn_data
->
spawn_is_single
),
&
displs
[
2
]);
MPI_Get_address
(
&
(
spawn_data
->
spawn_method
),
&
displs
[
3
]);
for
(
i
=
0
;
i
<
counts
;
i
++
)
displs
[
i
]
-=
dir
;
MPI_Type_create_struct
(
counts
,
blocklengths
,
displs
,
types
,
&
(
spawn_data
->
dtype
));
MPI_Type_commit
(
&
(
spawn_data
->
dtype
));
}
/*
* Libera una estructura de datos spawn_data
* junto a la destrucion de aquellas estructuras que utiliza.
*/
void
deallocate_spawn_data
()
{
if
(
spawn_data
==
NULL
)
return
;
if
(
spawn_data
->
cmd
!=
NULL
)
{
free
(
spawn_data
->
cmd
);
}
if
(
spawn_data
->
dtype
!=
MPI_DATATYPE_NULL
)
{
MPI_Type_free
(
&
(
spawn_data
->
dtype
));
}
if
(
spawn_data
->
mapping
!=
MPI_INFO_NULL
)
{
MPI_Info_free
(
&
(
spawn_data
->
mapping
));
}
if
(
spawn_data
->
spawn_is_async
)
{
free_spawn_state
();
}
free
(
spawn_data
);
spawn_data
=
NULL
;
}
//--------------PRIVATE SPAWN CREATION FUNCTIONS---------------//
/*
* Funcion generica para la creacion de procesos. Obtiene la configuracion
* y segun esta, elige como deberian crearse los procesos.
*
* Cuando termina, modifica la variable global para indicar este cambio
*/
void
generic_spawn
(
MPI_Comm
*
child
,
int
data_stage
)
{
int
local_state
,
aux_state
;
// WORK
if
(
spawn_data
->
myId
==
spawn_data
->
root
&&
spawn_data
->
spawn_qty
>
0
)
{
//SET MAPPING FOR NEW PROCESSES
processes_dist
(
spawn_data
->
dist
,
&
(
spawn_data
->
mapping
));
}
switch
(
spawn_data
->
spawn_method
)
{
case
MALL_SPAWN_BASELINE
:
local_state
=
baseline
(
*
spawn_data
,
child
);
break
;
case
MALL_SPAWN_MERGE
:
local_state
=
merge
(
*
spawn_data
,
child
,
data_stage
);
break
;
}
// END WORK
end_time
=
MPI_Wtime
();
aux_state
=
get_spawn_state
(
spawn_data
->
spawn_is_async
);
if
(
!
(
aux_state
==
MALL_SPAWN_PENDING
&&
local_state
==
MALL_SPAWN_ADAPT_POSTPONE
))
{
set_spawn_state
(
local_state
,
spawn_data
->
spawn_is_async
);
}
}
//--------------PRIVATE THREAD FUNCTIONS---------------//
/*
* Aloja la memoria para un hilo auxiliar dedicado a la creacion de procesos.
* No se puede realizar un "join" sobre el hilo y el mismo libera su memoria
* asociado al terminar.
*/
int
allocate_thread_spawn
()
{
if
(
pthread_create
(
&
spawn_thread
,
NULL
,
thread_work
,
NULL
))
{
printf
(
"Error al crear el hilo de SPAWN
\n
"
);
MPI_Abort
(
MPI_COMM_WORLD
,
-
1
);
return
-
1
;
}
if
(
pthread_detach
(
spawn_thread
))
{
printf
(
"Error when detaching spawning thread
\n
"
);
MPI_Abort
(
MPI_COMM_WORLD
,
-
1
);
return
-
1
;
}
return
0
;
}
/*
* Funcion llamada por un hilo para que este se encarge
* de configurar la creacion de un nuevo grupo de procesos.
*
* Una vez esta lista la configuracion y es posible crear los procesos
* se avisa al hilo maestro.
*/
void
*
thread_work
()
{
int
local_state
;
returned_comm
=
(
MPI_Comm
*
)
malloc
(
sizeof
(
MPI_Comm
));
generic_spawn
(
returned_comm
,
MALL_NOT_STARTED
);
local_state
=
get_spawn_state
(
MALL_SPAWN_PTHREAD
);
if
(
local_state
==
MALL_SPAWN_ADAPT_POSTPONE
||
local_state
==
MALL_SPAWN_PENDING
)
{
// El grupo de procesos se terminara de juntar tras la redistribucion de datos
local_state
=
wait_wakeup
();
generic_spawn
(
returned_comm
,
MALL_DIST_COMPLETED
);
}
pthread_exit
(
NULL
);
}
/*
* Comprueba si una creacion de procesos asincrona en el
* paso "single" ha terminado.
* Si no ha terminado se mantiene el estado
* "MALL_SPAWN_SINGLE_PENDING".
*
* Si ha terminado se crean los hilos auxiliares para
* los procesos no root y se devuelve el estado
* "MALL_SPAWN_PENDING".
*/
int
check_single_state
(
MPI_Comm
comm
,
int
global_state
)
{
MPI_Bcast
(
&
global_state
,
1
,
MPI_INT
,
spawn_data
->
root
,
comm
);
// Non-root processes join root to finalize the spawn
// They also must join if the application has ended its work
if
(
global_state
==
MALL_SPAWN_SINGLE_COMPLETED
)
{
global_state
=
MALL_SPAWN_PENDING
;
set_spawn_state
(
global_state
,
MALL_SPAWN_PTHREAD
);
if
(
spawn_data
->
myId
!=
spawn_data
->
root
)
{
allocate_thread_spawn
(
spawn_data
);
}
}
return
global_state
;
}
/*
* Comprueba si una creación de procesos asincrona en el
* paso "generic" ha terminado.
* Si no ha terminado devuelve el estado
* "MALL_SPAWN_PENDING".
*
* Si ha terminado libera la memoria asociada a spawn_data
* y devuelve el estado "MALL_SPAWN_COMPLETED".
*/
int
check_generic_state
(
MPI_Comm
comm
,
MPI_Comm
*
child
,
int
local_state
,
double
*
real_time
)
{
int
global_state
;
MPI_Allreduce
(
&
local_state
,
&
global_state
,
1
,
MPI_INT
,
MPI_MIN
,
comm
);
if
(
global_state
==
MALL_SPAWN_COMPLETED
||
global_state
==
MALL_SPAWN_ADAPTED
)
{
set_spawn_state
(
global_state
,
MALL_SPAWN_PTHREAD
);
*
child
=
*
returned_comm
;
deallocate_spawn_data
(
spawn_data
);
*
real_time
=
end_time
;
}
return
global_state
;
}
malleability/spawn_methods/GenericSpawn.h
0 → 100644
View file @
95f9a9a6
#ifndef MALLEABILITY_GENERIC_SPAWN_H
#define MALLEABILITY_GENERIC_SPAWN_H
#include <stdio.h>
#include <stdlib.h>
#include <mpi.h>
#include "../malleabilityDataStructures.h"
int
init_spawn
(
char
*
argv
,
int
num_cpus
,
int
num_nodes
,
char
*
nodelist
,
int
myId
,
int
initial_qty
,
int
target_qty
,
int
root
,
int
type_dist
,
int
spawn_method
,
int
spawn_strategies
,
MPI_Comm
comm
,
MPI_Comm
*
child
);
int
check_spawn_state
(
MPI_Comm
*
child
,
MPI_Comm
comm
,
double
*
real_time
);
void
malleability_connect_children
(
int
myId
,
int
numP
,
int
root
,
MPI_Comm
comm
,
int
*
numP_parents
,
int
*
root_parents
,
MPI_Comm
*
parents
);
void
unset_spawn_postpone_flag
(
int
outside_state
);
int
malleability_spawn_contains_strat
(
int
spawn_strategies
,
int
strategy
,
int
*
result
);
#endif
malleability/spawn_methods/Merge.c
0 → 100644
View file @
95f9a9a6
#include <stdio.h>
#include <stdlib.h>
#include <mpi.h>
#include "../malleabilityStates.h"
#include "Merge.h"
#include "Baseline.h"
//--------------PRIVATE DECLARATIONS---------------//
void
merge_adapt_expand
(
MPI_Comm
*
child
,
int
is_children_group
);
void
merge_adapt_shrink
(
int
numC
,
MPI_Comm
*
child
,
MPI_Comm
comm
,
int
myId
);
//--------------PUBLIC FUNCTIONS---------------//
int
merge
(
Spawn_data
spawn_data
,
MPI_Comm
*
child
,
int
data_state
)
{
MPI_Comm
intercomm
;
int
local_state
;
int
is_children_group
=
1
;
if
(
spawn_data
.
initial_qty
>
spawn_data
.
target_qty
)
{
//Shrink
if
(
data_state
==
MALL_DIST_COMPLETED
)
{
merge_adapt_shrink
(
spawn_data
.
target_qty
,
child
,
spawn_data
.
comm
,
spawn_data
.
myId
);
local_state
=
MALL_SPAWN_ADAPTED
;
}
else
{
local_state
=
MALL_SPAWN_ADAPT_POSTPONE
;
}
}
else
{
//Expand
MPI_Comm_get_parent
(
&
intercomm
);
is_children_group
=
intercomm
==
MPI_COMM_NULL
?
0
:
1
;
baseline
(
spawn_data
,
child
);
merge_adapt_expand
(
child
,
is_children_group
);
local_state
=
MALL_SPAWN_COMPLETED
;
}
return
local_state
;
}
//--------------PRIVATE MERGE TYPE FUNCTIONS---------------//
/*
* Se encarga de que el grupo de procesos resultante se
* encuentren todos en un intra comunicador, uniendo a
* padres e hijos en un solo comunicador.
*
* Se llama antes de la redistribución de datos.
*
* TODO REFACTOR
*/
void
merge_adapt_expand
(
MPI_Comm
*
child
,
int
is_children_group
)
{
MPI_Comm
new_comm
=
MPI_COMM_NULL
;
MPI_Intercomm_merge
(
*
child
,
is_children_group
,
&
new_comm
);
//El que pone 0 va primero
MPI_Comm_free
(
child
);
//POSIBLE ERROR?
*
child
=
new_comm
;
//*numP = numC; //TODO REFACTOR Llevar a otra parte -- Hacer solo si MALL_SPAWN_ADAPTED
//if(*comm != MPI_COMM_WORLD && *comm != MPI_COMM_NULL) {
// MPI_Comm_free(comm);
//}
}
/*
* Se encarga de que el grupo de procesos resultante se
* eliminen aquellos procesos que ya no son necesarios.
* Los procesos eliminados se quedaran como zombies.
*
* Se llama una vez ha terminado la redistribución de datos.
*/
void
merge_adapt_shrink
(
int
numC
,
MPI_Comm
*
child
,
MPI_Comm
comm
,
int
myId
)
{
int
color
=
MPI_UNDEFINED
;
if
(
myId
<
numC
)
{
color
=
1
;
}
MPI_Comm_split
(
comm
,
color
,
myId
,
child
);
}
malleability/spawn_methods/Merge.h
0 → 100644
View file @
95f9a9a6
#ifndef MALLEABILITY_SPAWN_MERGE_H
#define MALLEABILITY_SPAWN_MERGE_H
#include <stdio.h>
#include <stdlib.h>
#include <mpi.h>
#include "../malleabilityDataStructures.h"
int
merge
(
Spawn_data
spawn_data
,
MPI_Comm
*
child
,
int
data_state
);
#endif
malleability/spawn_methods/ProcessDist.c
0 → 100644
View file @
95f9a9a6
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <mpi.h>
#include "ProcessDist.h"
//#define USE_SLURM
//--------------PRIVATE DECLARATIONS---------------//
void
node_dist
(
struct
physical_dist
dist
,
int
**
qty
,
int
*
used_nodes
);
void
spread_dist
(
struct
physical_dist
dist
,
int
*
used_nodes
,
int
*
procs
);
void
compact_dist
(
struct
physical_dist
dist
,
int
*
used_nodes
,
int
*
procs
);
void
generate_info_string
(
int
target_qty
,
MPI_Info
*
info
);
//--------------------------------SLURM USAGE-------------------------------------//
#ifdef USE_SLURM
#include <slurm/slurm.h>
void
generate_info_string_slurm
(
char
*
nodelist
,
int
*
procs_array
,
size_t
nodes
,
MPI_Info
*
info
);
void
fill_str_hosts_slurm
(
char
*
nodelist
,
int
*
qty
,
size_t
used_nodes
,
char
**
hostfile_str
);
//@deprecated functions
void
generate_info_hostfile_slurm
(
char
*
nodelist
,
int
*
procs_array
,
int
nodes
,
MPI_Info
*
info
);
void
fill_hostfile_slurm
(
char
*
nodelist
,
int
ptr
,
int
*
qty
,
int
used_nodes
);
#endif
//--------------------------------SLURM USAGE-------------------------------------//
int
write_str_node
(
char
**
hostfile_str
,
size_t
len_og
,
size_t
qty
,
char
*
node_name
);
//@deprecated functions
int
create_hostfile
(
char
**
file_name
);
int
write_hostfile_node
(
int
ptr
,
int
qty
,
char
*
node_name
);
//--------------PUBLIC FUNCTIONS---------------//
/*
* Pone los datos para una estructura que guarda los parametros
* para realizar un mappeado de los procesos.
*
* Si la memoria no esta reservada devuelve falso y no hace nada.
* Si puede realizar los cambios devuelve verdadero.
*
* IN parameters -->
* target_qty: Numero de procesos tras la reconfiguracion
* alreadyCreated: Numero de procesos padre a considerar
* La resta de target_qty-alreadyCreated es el numero de hijos a crear
* num_cpus: Numero de cpus totales (En uso o no)
* num_nodes: Numero de nodos disponibles por esta aplicacion
* info_type: Indica como realizar el mappeado, si indicarlo
* en una cadena (MALL_DIST_STRING) o en un hostfile
* (MALL_DIST_HOSTFILE)
* dist_type: Indica como sera el mappeado, si intentar rellenar
* primero los nodos con cpus ya usados (CPUS/BEST/COMPACT) o
* que todos los nodos tengan el mismo numero de cpus usados
* (NODES/WORST/SPREAD)
*/
int
physical_struct_create
(
int
target_qty
,
int
already_created
,
int
num_cpus
,
int
num_nodes
,
char
*
nodelist
,
int
dist_type
,
int
info_type
,
struct
physical_dist
*
dist
)
{
dist
->
target_qty
=
target_qty
;
dist
->
already_created
=
already_created
;
dist
->
num_cpus
=
num_cpus
;
dist
->
num_nodes
=
num_nodes
;
dist
->
nodelist
=
nodelist
;
dist
->
dist_type
=
dist_type
;
dist
->
info_type
=
info_type
;
return
1
;
}
/*
* Configura la creacion de un nuevo grupo de procesos, reservando la memoria
* para una llamada a MPI_Comm_spawn, obteniendo una distribucion fisica
* para los procesos y creando un fichero hostfile.
*
* OUT parameters -->
* info_spawn: Objeto MPI_Info en el que se indica el mappeado
* a usar al crear los procesos.
*/
void
processes_dist
(
struct
physical_dist
dist
,
MPI_Info
*
info_spawn
)
{
#ifdef USE_SLURM
int
used_nodes
=
0
;
int
*
procs_array
;
// GET NEW DISTRIBUTION
node_dist
(
dist
,
&
procs_array
,
&
used_nodes
);
switch
(
dist
.
info_type
)
{
case
MALL_DIST_STRING
:
generate_info_string_slurm
(
dist
.
nodelist
,
procs_array
,
used_nodes
,
info_spawn
);
break
;
case
MALL_DIST_HOSTFILE
:
generate_info_hostfile_slurm
(
dist
.
nodelist
,
procs_array
,
used_nodes
,
info_spawn
);
break
;
}
free
(
procs_array
);
#else
//generate_info_string(dist.target_qty, info_spawn);
#endif
}
//--------------PRIVATE FUNCTIONS---------------//
//-----------------DISTRIBUTION-----------------//
/*
* Obtiene la distribucion fisica del grupo de procesos a crear, devolviendo
* cuantos nodos se van a utilizar y la cantidad de procesos que alojara cada
* nodo.
*
* Se permiten dos tipos de distribuciones fisicas segun el valor de "dist_type":
*
* COMM_PHY_NODES (1): Orientada a equilibrar el numero de procesos entre
* todos los nodos disponibles.
* COMM_PHY_CPU (2): Orientada a completar la capacidad de un nodo antes de
* ocupar otro nodo.
*/
void
node_dist
(
struct
physical_dist
dist
,
int
**
qty
,
int
*
used_nodes
)
{
int
i
,
*
procs
;
procs
=
calloc
(
dist
.
num_nodes
,
sizeof
(
int
));
// Numero de procesos por nodo
/* GET NEW DISTRIBUTION */
switch
(
dist
.
dist_type
)
{
case
MALL_DIST_SPREAD
:
// DIST NODES @deprecated
spread_dist
(
dist
,
used_nodes
,
procs
);
break
;
case
MALL_DIST_COMPACT
:
// DIST CPUs
compact_dist
(
dist
,
used_nodes
,
procs
);
break
;
}
//Copy results to output vector qty
*
qty
=
calloc
(
*
used_nodes
,
sizeof
(
int
));
// Numero de procesos por nodo
for
(
i
=
0
;
i
<
*
used_nodes
;
i
++
)
{
(
*
qty
)[
i
]
=
procs
[
i
];
}
free
(
procs
);
}
/*
* Distribucion basada en equilibrar el numero de procesos en cada nodo
* para que todos los nodos tengan el mismo numero. Devuelve el total de
* nodos utilizados y el numero de procesos a crear en cada nodo.
*
* TODO Tener en cuenta procesos ya creados (already_created)
*/
void
spread_dist
(
struct
physical_dist
dist
,
int
*
used_nodes
,
int
*
procs
)
{
int
i
,
tamBl
,
remainder
;
*
used_nodes
=
dist
.
num_nodes
;
tamBl
=
dist
.
target_qty
/
dist
.
num_nodes
;
remainder
=
dist
.
target_qty
%
dist
.
num_nodes
;
for
(
i
=
0
;
i
<
remainder
;
i
++
)
{
procs
[
i
]
=
tamBl
+
1
;
}
for
(
i
=
remainder
;
i
<
dist
.
num_nodes
;
i
++
)
{
procs
[
i
]
=
tamBl
;
}
}
/*
* Distribucion basada en llenar un nodo de procesos antes de pasar al
* siguiente nodo. Devuelve el total de nodos utilizados y el numero
* de procesos a crear en cada nodo.
*
* Tiene en cuenta los procesos ya existentes para el mappeado de
* los procesos a crear.
*/
void
compact_dist
(
struct
physical_dist
dist
,
int
*
used_nodes
,
int
*
procs
)
{
int
i
,
asigCores
;
int
tamBl
,
remainder
;
tamBl
=
dist
.
num_cpus
/
dist
.
num_nodes
;
asigCores
=
dist
.
already_created
;
i
=
*
used_nodes
=
dist
.
already_created
/
tamBl
;
remainder
=
dist
.
already_created
%
tamBl
;
//FIXME REFACTOR Que pasa si los nodos 1 y 2 tienen espacios libres
//First nodes could already have existing procs
//Start from the first with free spaces
if
(
remainder
)
{
procs
[
i
]
=
tamBl
-
remainder
;
asigCores
+=
procs
[
i
];
i
=
(
i
+
1
)
%
dist
.
num_nodes
;
(
*
used_nodes
)
++
;
}
//Assign tamBl to each node
while
(
asigCores
+
tamBl
<=
dist
.
target_qty
)
{
asigCores
+=
tamBl
;
procs
[
i
]
+=
tamBl
;
i
=
(
i
+
1
)
%
dist
.
num_nodes
;
(
*
used_nodes
)
++
;
}
//Last node could have less procs than tamBl
if
(
asigCores
<
dist
.
target_qty
)
{
procs
[
i
]
+=
dist
.
target_qty
-
asigCores
;
(
*
used_nodes
)
++
;
}
if
(
*
used_nodes
>
dist
.
num_nodes
)
*
used_nodes
=
dist
.
num_nodes
;
//FIXME Si ocurre esto no es un error?
}
//--------------PRIVATE FUNCTIONS---------------//
//-------------------INFO SET-------------------//
/*
* Crea y devuelve un objeto MPI_Info con un par hosts/mapping
* en el que se indica el mappeado a utilizar en los nuevos
* procesos.
*
* Actualmente no considera que puedan haber varios nodos
* y lleva todos al mismo. Las funciones "generate_info_string_slurm"
* o "generate_info_hostfile_slurm" permiten utilizar varios
* nodos, pero es necesario activar Slurm.
*/
void
generate_info_string
(
int
target_qty
,
MPI_Info
*
info
){
char
*
host_string
,
*
host
;
int
len
,
err
;
host
=
"localhost"
;
//host = malloc(MPI_MAX_PROCESSOR_NAME * sizeof(char));
//MPI_Get_processor_name(host, &len);
// CREATE AND SET STRING HOSTS
err
=
write_str_node
(
&
host_string
,
0
,
target_qty
,
host
);
if
(
err
<
0
)
{
printf
(
"Error when generating mapping: %d
\n
"
,
err
);
MPI_Abort
(
MPI_COMM_WORLD
,
err
);}
// SET MAPPING
MPI_Info_create
(
info
);
MPI_Info_set
(
*
info
,
"hosts"
,
host_string
);
//free(host);
free
(
host_string
);
}
//--------------------------------SLURM USAGE-------------------------------------//
#ifdef USE_SLURM
/*
* Crea y devuelve un objeto MPI_Info con un par hosts/mapping
* en el que se indica el mappeado a utilizar en los nuevos
* procesos.
* Es necesario usar Slurm para usarlo.
*/
void
generate_info_string_slurm
(
char
*
nodelist
,
int
*
procs_array
,
size_t
nodes
,
MPI_Info
*
info
){
// CREATE AND SET STRING HOSTS
char
*
hoststring
;
fill_str_hosts_slurm
(
nodelist
,
procs_array
,
nodes
,
&
hoststring
);
MPI_Info_create
(
info
);
MPI_Info_set
(
*
info
,
"hosts"
,
hoststring
);
free
(
hoststring
);
}
/*
* Crea y devuelve una cadena para ser utilizada por la llave "hosts"
* al crear procesos e indicar donde tienen que ser creados.
*/
void
fill_str_hosts_slurm
(
char
*
nodelist
,
int
*
qty
,
size_t
used_nodes
,
char
**
hostfile_str
)
{
char
*
host
;
size_t
i
=
0
,
len
=
0
;
hostlist_t
hostlist
;
hostlist
=
slurm_hostlist_create
(
nodelist
);
while
(
(
host
=
slurm_hostlist_shift
(
hostlist
))
&&
i
<
used_nodes
)
{
if
(
qty
[
i
]
!=
0
)
{
len
=
write_str_node
(
hostfile_str
,
len
,
qty
[
i
],
host
);
}
i
++
;
free
(
host
);
}
slurm_hostlist_destroy
(
hostlist
);
}
#endif
//--------------------------------SLURM USAGE-------------------------------------//
/*
* Añade en una cadena "qty" entradas de "node_name".
* Realiza la reserva de memoria y la realoja si es necesario.
*/
int
write_str_node
(
char
**
hostfile_str
,
size_t
len_og
,
size_t
qty
,
char
*
node_name
)
{
int
err
;
char
*
ocurrence
;
size_t
i
,
len
,
len_node
;
len_node
=
strlen
(
node_name
)
+
1
;
// Str length + ','
len
=
qty
*
len_node
;
// Number of times the node is used
if
(
len_og
==
0
)
{
// Memoria no reservada
*
hostfile_str
=
(
char
*
)
malloc
((
len
+
1
)
*
sizeof
(
char
));
}
else
{
// Cadena ya tiene datos
*
hostfile_str
=
(
char
*
)
realloc
(
*
hostfile_str
,
(
len_og
+
len
+
1
)
*
sizeof
(
char
));
}
if
(
hostfile_str
==
NULL
)
return
-
1
;
// No ha sido posible alojar la memoria
ocurrence
=
(
char
*
)
malloc
((
len_node
+
1
)
*
sizeof
(
char
));
if
(
ocurrence
==
NULL
)
return
-
2
;
// No ha sido posible alojar la memoria
err
=
snprintf
(
ocurrence
,
len_node
+
1
,
",%s"
,
node_name
);
if
(
err
<
0
)
return
-
3
;
// No ha sido posible escribir sobre la variable auxiliar
i
=
0
;
if
(
len_og
==
0
)
{
// Si se inicializa, la primera es una copia
i
++
;
strcpy
(
*
hostfile_str
,
node_name
);
}
for
(;
i
<
qty
;
i
++
){
// Las siguientes se conctanenan
strcat
(
*
hostfile_str
,
ocurrence
);
}
free
(
ocurrence
);
return
len
+
len_og
;
}
//====================================================
//====================================================
//============DEPRECATED FUNCTIONS====================
//====================================================
//====================================================
//--------------------------------SLURM USAGE-------------------------------------//
#ifdef USE_SLURM
/* FIXME Por revisar
* @deprecated
* Genera un fichero hostfile y lo anyade a un objeto
* MPI_Info para ser utilizado.
*/
void
generate_info_hostfile_slurm
(
char
*
nodelist
,
int
*
procs_array
,
int
nodes
,
MPI_Info
*
info
){
char
*
hostfile
;
int
ptr
;
// CREATE/UPDATE HOSTFILE
ptr
=
create_hostfile
(
&
hostfile
);
MPI_Info_create
(
info
);
MPI_Info_set
(
*
info
,
"hostfile"
,
hostfile
);
free
(
hostfile
);
// SET NEW DISTRIBUTION
fill_hostfile_slurm
(
nodelist
,
ptr
,
procs_array
,
nodes
);
close
(
ptr
);
}
/*
* @deprecated
* Crea un fichero que se utilizara como hostfile
* para un nuevo grupo de procesos.
*
* El nombre es devuelto en el argumento "file_name",
* que tiene que ser un puntero vacio.
*
* Ademas se devuelve un descriptor de fichero para
* modificar el fichero.
*/
int
create_hostfile
(
char
**
file_name
)
{
int
ptr
,
err
;
size_t
len
=
11
;
//FIXME Numero mágico
*
file_name
=
NULL
;
*
file_name
=
malloc
(
len
*
sizeof
(
char
));
if
(
*
file_name
==
NULL
)
return
-
1
;
// No ha sido posible alojar la memoria
err
=
snprintf
(
*
file_name
,
len
,
"hostfile.o"
);
if
(
err
<
0
)
return
-
2
;
// No ha sido posible obtener el nombre de fichero
ptr
=
open
(
*
file_name
,
O_WRONLY
|
O_CREAT
|
O_TRUNC
,
0644
);
if
(
ptr
<
0
)
return
-
3
;
// No ha sido posible crear el fichero
return
ptr
;
// Devolver puntero a fichero
}
/*
* @deprecated
* Rellena un fichero hostfile indicado por ptr con los nombres
* de los nodos a utilizar indicados por "job_record" y la cantidad
* de procesos que alojara cada nodo indicado por "qty".
*/
void
fill_hostfile_slurm
(
char
*
nodelist
,
int
ptr
,
int
*
qty
,
int
nodes
)
{
int
i
=
0
;
char
*
host
;
hostlist_t
hostlist
;
hostlist
=
slurm_hostlist_create
(
nodelist
);
while
((
host
=
slurm_hostlist_shift
(
hostlist
))
&&
i
<
nodes
)
{
write_hostfile_node
(
ptr
,
qty
[
i
],
host
);
i
++
;
free
(
host
);
}
slurm_hostlist_destroy
(
hostlist
);
}
/*
* @deprecated
* Escribe en el fichero hostfile indicado por ptr una nueva linea.
*
* Esta linea indica el nombre de un nodo y la cantidad de procesos a
* alojar en ese nodo.
*/
int
write_hostfile_node
(
int
ptr
,
int
qty
,
char
*
node_name
)
{
int
err
;
char
*
line
;
size_t
len
,
len_node
,
len_int
;
len_node
=
strlen
(
node_name
);
err
=
snprintf
(
NULL
,
0
,
"%d"
,
qty
);
if
(
err
<
0
)
return
-
1
;
len_int
=
err
;
len
=
len_node
+
len_int
+
3
;
line
=
malloc
(
len
*
sizeof
(
char
));
if
(
line
==
NULL
)
return
-
2
;
// No ha sido posible alojar la memoria
err
=
snprintf
(
line
,
len
,
"%s:%d
\n
"
,
node_name
,
qty
);
if
(
err
<
0
)
return
-
3
;
// No ha sido posible escribir en el fichero
write
(
ptr
,
line
,
len
-
1
);
free
(
line
);
return
0
;
}
#endif
//--------------------------------SLURM USAGE-------------------------------------//
//TODO REFACTOR PARA CUANDO SE COMUNIQUE CON RMS
// Get Slurm job info
//int jobId;
//char *tmp;
//job_info_msg_t *j_info;
//slurm_job_info_t last_record;
//tmp = getenv("SLURM_JOB_ID");
//jobId = atoi(tmp);
//slurm_load_job(&j_info, jobId, 1);
//last_record = j_info->job_array[j_info->record_count - 1];
// Free JOB INFO
//slurm_free_job_info_msg(j_info);
malleability/spawn_methods/ProcessDist.h
0 → 100644
View file @
95f9a9a6
#ifndef MALLEABILITY_SPAWN_PROCESS_DIST_H
#define MALLEABILITY_SPAWN_PROCESS_DIST_H
#include <stdio.h>
#include <stdlib.h>
#include <mpi.h>
#include <string.h>
#include "../malleabilityStates.h"
#include "../malleabilityDataStructures.h"
#define MALL_DIST_SPREAD 1
#define MALL_DIST_COMPACT 2
#define MALL_DIST_STRING 1
#define MALL_DIST_HOSTFILE 2
int
physical_struct_create
(
int
target_qty
,
int
already_created
,
int
num_cpus
,
int
num_nodes
,
char
*
nodelist
,
int
dist_type
,
int
info_type
,
struct
physical_dist
*
dist
);
void
processes_dist
(
struct
physical_dist
dist
,
MPI_Info
*
info_spawn
);
#endif
malleability/spawn_methods/Spawn_state.c
0 → 100644
View file @
95f9a9a6
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include "Spawn_state.h"
pthread_mutex_t
spawn_mutex
;
pthread_cond_t
spawn_cond
;
int
spawn_state
;
int
waiting_redistribution
=
0
;
void
init_spawn_state
()
{
pthread_mutex_init
(
&
spawn_mutex
,
NULL
);
pthread_cond_init
(
&
spawn_cond
,
NULL
);
set_spawn_state
(
1
,
0
);
//FIXME First parameter is a horrible magical number
}
void
free_spawn_state
()
{
pthread_mutex_destroy
(
&
spawn_mutex
);
pthread_cond_destroy
(
&
spawn_cond
);
}
int
get_spawn_state
(
int
is_async
)
{
int
value
;
if
(
is_async
)
{
pthread_mutex_lock
(
&
spawn_mutex
);
value
=
spawn_state
;
pthread_mutex_unlock
(
&
spawn_mutex
);
}
else
{
value
=
spawn_state
;
}
return
value
;
}
void
set_spawn_state
(
int
value
,
int
is_async
)
{
if
(
is_async
)
{
pthread_mutex_lock
(
&
spawn_mutex
);
spawn_state
=
value
;
pthread_mutex_unlock
(
&
spawn_mutex
);
}
else
{
spawn_state
=
value
;
}
}
int
wait_wakeup
()
{
pthread_mutex_lock
(
&
spawn_mutex
);
if
(
!
waiting_redistribution
)
{
waiting_redistribution
=
1
;
pthread_cond_wait
(
&
spawn_cond
,
&
spawn_mutex
);
}
waiting_redistribution
=
0
;
pthread_mutex_unlock
(
&
spawn_mutex
);
return
get_spawn_state
(
1
);
}
void
wakeup
()
{
pthread_mutex_lock
(
&
spawn_mutex
);
if
(
waiting_redistribution
)
{
pthread_cond_signal
(
&
spawn_cond
);
}
waiting_redistribution
=
1
;
pthread_mutex_unlock
(
&
spawn_mutex
);
}
malleability/spawn_methods/Spawn_state.h
0 → 100644
View file @
95f9a9a6
#ifndef MALLEABILITY_SPAWN_STATE_H
#define MALLEABILITY_SPAWN_STATE_H
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
void
init_spawn_state
();
void
free_spawn_state
();
int
get_spawn_state
(
int
is_async
);
void
set_spawn_state
(
int
value
,
int
is_async
);
int
wait_wakeup
();
void
wakeup
();
#endif
run.sh
0 → 100644
View file @
95f9a9a6
#!/bin/bash
#SBATCH -N 1
#SBATCH -p P1
#SBATCH -t 00:10:00
module load /home/martini/MODULES/modulefiles/mpich-4.0.3-ofi
module load /home/martini/MODULES/modulefiles/intel64Only.module
echo
"Test"
mpirun
-np
4 ./build/a.out bcsstk01.rsa 2 n00 1
#mpirun -np 4 ./ConjugateGradient bcsstk17.rsa
#mpirun -np 8 ./ConjugateGradient bcsstk01.rsa
#mpirun -np 12 ./ConjugateGradient bcsstk01.rsa
echo
"AUDIK"
#mpirun -np 4 ./ConjugateGradient ../../audikw_1/audikw_1.rb
#mpirun -np 4 ./ConjugateGradient ../../audikw_1/audikw_1.rb
#mpirun -np 4 ./ConjugateGradient ../../audikw_1/audikw_1.rb
echo
"End"
Prev
1
2
Next
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment