Skip to content

Commit 2eb2f04

Browse files
committed
Transfer data to and from GPU.
This is a multi-part patch that allows the CPU to prepare a data copy mapped onto a device. 1. The first question is how is such a device selected ? The allocation of such a copy happen way before the scheduler is invoked for a task, in fact before the task is even ready. Thus, we need to decide on the location of this copy only based on some static information, such as the task affinity. Therefore, this approach only works for owner-compute type of tasks, where the task will be executed on the device that owns the data used for the task affinity. 2. Pass the correct data copy across the entire system, instead of falling back to data copy of the device 0 (CPU memory) Signed-off-by: George Bosilca <gbosilca@nvidia.com>
1 parent 879fad3 commit 2eb2f04

File tree

14 files changed

+320
-91
lines changed

14 files changed

+320
-91
lines changed

parsec/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,7 @@ if( BUILD_PARSEC )
238238
$<$<BOOL:${PARSEC_HAVE_OTF2}>:OTF2::OTF2>
239239
$<$<BOOL:${MPI_C_FOUND}>:MPI::MPI_C>
240240
$<$<BOOL:${PARSEC_HAVE_CUDA}>:CUDA::cudart>
241+
$<$<BOOL:${PARSEC_HAVE_CUDA}>:cuda>
241242
$<$<BOOL:${PARSEC_HAVE_HIP}>:hip::host>
242243
${EXTRA_LIBS}
243244
INTERFACE

parsec/arena.c

Lines changed: 68 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -235,43 +235,89 @@ int parsec_arena_allocate_device_private(parsec_data_copy_t *copy,
235235
return PARSEC_SUCCESS;
236236
}
237237

238-
parsec_data_copy_t *parsec_arena_get_copy(parsec_arena_t *arena,
239-
size_t count, int device,
240-
parsec_datatype_t dtt)
238+
#include "parsec/utils/zone_malloc.h"
239+
#include "mca/device/device_gpu.h"
240+
241+
static inline parsec_data_copy_t *
242+
parsec_arena_internal_copy_new(parsec_arena_t *arena,
243+
parsec_data_t *data,
244+
size_t count, int device,
245+
parsec_datatype_t dtt)
241246
{
242-
parsec_data_t *data;
243247
parsec_data_copy_t *copy;
244-
int rc;
245-
246-
247-
data = parsec_data_new();
248248
if( NULL == data ) {
249+
data = parsec_data_new();
250+
if( NULL == data ) {
251+
return NULL;
252+
}
253+
}
254+
copy = parsec_data_copy_new(data, device, dtt,
255+
PARSEC_DATA_FLAG_PARSEC_OWNED | PARSEC_DATA_FLAG_PARSEC_MANAGED);
256+
257+
if (NULL == copy) {
258+
PARSEC_OBJ_RELEASE(data);
249259
return NULL;
250260
}
261+
if( 0 == device ) {
262+
copy->flags |= PARSEC_DATA_FLAG_ARENA; /* allocated from an arena */
263+
int rc = parsec_arena_allocate_device_private(copy, arena, count, device, dtt);
264+
if (PARSEC_SUCCESS != rc) {
265+
PARSEC_OBJ_RELEASE(copy);
266+
return NULL;
267+
}
268+
return copy;
269+
}
270+
parsec_device_gpu_module_t *gpu_device = (parsec_device_gpu_module_t*)parsec_mca_device_get(device);
271+
if( NULL == gpu_device ) {
272+
PARSEC_OBJ_RELEASE(copy);
273+
return NULL;
274+
}
275+
size_t size = count * arena->elem_size;
251276

252-
copy = parsec_data_copy_new( data, device, dtt,
253-
PARSEC_DATA_FLAG_ARENA |
254-
PARSEC_DATA_FLAG_PARSEC_OWNED |
255-
PARSEC_DATA_FLAG_PARSEC_MANAGED);
277+
copy->dtt = dtt;
278+
copy->device_private = zone_malloc(gpu_device->memory, size);
279+
copy->arena_chunk = (parsec_arena_chunk_t*)gpu_device->memory;
280+
PARSEC_DEBUG_VERBOSE(10, parsec_debug_output, "Arena:\tallocate data copy on device %d of size %zu from zone %p, "
281+
"data ptr %p",
282+
device, size, (void*)copy->arena_chunk, (void*)copy->device_private);
256283

257-
if(NULL == copy) {
258-
PARSEC_OBJ_RELEASE(data);
284+
if( NULL == copy->device_private ) {
285+
PARSEC_OBJ_RELEASE(copy);
259286
return NULL;
260287
}
288+
copy->version = 0;
289+
copy->coherency_state = PARSEC_DATA_COHERENCY_INVALID;
290+
copy->original->owner_device = device;
291+
copy->original->preferred_device = device;
292+
return copy;
293+
}
261294

262-
rc = parsec_arena_allocate_device_private(copy, arena, count, device, dtt);
295+
parsec_data_copy_t *parsec_arena_get_copy(parsec_arena_t *arena,
296+
size_t count, int device,
297+
parsec_datatype_t dtt)
298+
{
299+
parsec_data_copy_t *dev0_copy, *copy;
263300

301+
dev0_copy = parsec_arena_internal_copy_new(arena, NULL, count, 0 /* first allocate the copy on the device 0 */, dtt);
302+
if( NULL == dev0_copy ) {
303+
return NULL;
304+
}
305+
dev0_copy->coherency_state = PARSEC_DATA_COHERENCY_INVALID;
306+
dev0_copy->version = 0; /* start from somewhere */
307+
if( 0 == device ) {
308+
return dev0_copy;
309+
}
310+
311+
copy = parsec_arena_internal_copy_new(arena, dev0_copy->original, count, device, dtt);
312+
if( NULL == copy ) {
313+
PARSEC_OBJ_RELEASE(dev0_copy);
314+
return NULL;
315+
}
264316
/* This data is going to be released once all copies are released
265317
* It does not exist without at least a copy, and we don't give the
266318
* pointer to the user, so we must remove our retain from it
267319
*/
268-
PARSEC_OBJ_RELEASE(data);
269-
270-
if( PARSEC_SUCCESS != rc ) {
271-
PARSEC_OBJ_RELEASE(copy);
272-
return NULL;
273-
}
274-
320+
PARSEC_OBJ_RELEASE(dev0_copy->original);
275321
return copy;
276322
}
277323

parsec/data.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -330,6 +330,12 @@ int parsec_data_start_transfer_ownership_to_copy(parsec_data_t* data,
330330
copy = data->device_copies[device];
331331
assert( NULL != copy );
332332

333+
if( valid_copy == device ) {
334+
PARSEC_DEBUG_VERBOSE(10, parsec_debug_output,
335+
"DEV[%d]: already has ownership of data %p to copy %p in mode %d",
336+
device, data, copy, access_mode);
337+
goto bookkeeping;
338+
}
333339
PARSEC_DEBUG_VERBOSE(10, parsec_debug_output,
334340
"DEV[%d]: start transfer ownership of data %p to copy %p in mode %d",
335341
device, data, copy, access_mode);
@@ -417,6 +423,7 @@ int parsec_data_start_transfer_ownership_to_copy(parsec_data_t* data,
417423
}
418424
}
419425

426+
bookkeeping:
420427
if( PARSEC_FLOW_ACCESS_READ & access_mode ) {
421428
copy->readers++;
422429
}

parsec/data.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,9 @@ typedef uint8_t parsec_data_coherency_t;
3131
#define PARSEC_DATA_COHERENCY_SHARED ((parsec_data_coherency_t)0x4)
3232

3333
typedef uint8_t parsec_data_status_t;
34-
#define PARSEC_DATA_STATUS_NOT_TRANSFER ((parsec_data_coherency_t)0x0)
35-
#define PARSEC_DATA_STATUS_UNDER_TRANSFER ((parsec_data_coherency_t)0x1)
36-
#define PARSEC_DATA_STATUS_COMPLETE_TRANSFER ((parsec_data_coherency_t)0x2)
34+
#define PARSEC_DATA_STATUS_NOT_TRANSFER ((parsec_data_status_t)0x0)
35+
#define PARSEC_DATA_STATUS_UNDER_TRANSFER ((parsec_data_status_t)0x1)
36+
#define PARSEC_DATA_STATUS_COMPLETE_TRANSFER ((parsec_data_status_t)0x2)
3737
/**
3838
* Data copies have three levels of 'ownership':
3939
* - a data copy can be owned and managed by PaRSEC.

parsec/data_dist/matrix/two_dim_rectangle_cyclic.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,6 @@ typedef struct parsec_matrix_block_cyclic {
4545
* @param dc matrix description structure, already allocated, that will be initialize
4646
* @param mtype type of data used for this matrix
4747
* @param storage type of storage of data
48-
* @param nodes number of nodes
4948
* @param myrank rank of the local node (as of mpi rank)
5049
* @param mb number of row in a tile
5150
* @param nb number of column in a tile

parsec/interfaces/ptg/ptg-compiler/jdf2c.c

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -672,6 +672,17 @@ static char* dump_local_assignments( void** elem, void* arg )
672672
if( dos > 0 ) {
673673
string_arena_init(info->sa);
674674
string_arena_add_string(info->sa, "const int %s = %s%s.value;", def->name, info->holder, def->name);
675+
#if 0
676+
jdf_expr_t* type_str = jdf_find_property( def->properties, "type", NULL );
677+
if( NULL == type_str ) {
678+
string_arena_add_string(info->sa, "const int %s = %s%s.value;", def->name, info->holder, def->name);
679+
} else {
680+
expr_info_t expr_info = {.sa = info->sa, .prefix = "", .suffix = "", .assignments = "locals"};
681+
string_arena_add_string(info->sa, "const %s %s = %s%s.value;",
682+
dump_expr((void**)type_str, &expr_info),
683+
def->name, info->holder, def->name);
684+
}
685+
#endif
675686
if( dos > 1 )
676687
string_arena_add_string(info->sa, " (void)%s;", def->name);
677688
return string_arena_get_string(info->sa);
@@ -5649,12 +5660,14 @@ jdf_generate_code_call_initialization(const jdf_t *jdf, const jdf_call_t *call,
56495660

56505661
/* Code to create & fulfill a reshape promise locally in case this input dependency is typed */
56515662
jdf_generate_code_reshape_input_from_dep(jdf, f, flow, dl, spaces);
5652-
coutput("%s this_task->data._f_%s.data_out = parsec_data_get_copy(chunk->original, target_device);\n"
5653-
"#if defined(PARSEC_PROF_GRAPHER) && defined(PARSEC_PROF_TRACE)\n"
5663+
/* We don't have to set the data_out anymore */
5664+
//coutput("%s this_task->data._f_%s.data_out = parsec_data_get_copy(chunk->original, target_device);\n",
5665+
// spaces, flow->varname);
5666+
5667+
coutput("#if defined(PARSEC_PROF_GRAPHER) && defined(PARSEC_PROF_TRACE)\n"
56545668
"%s parsec_prof_grapher_data_input(chunk->original, (parsec_task_t*)this_task, &%s, 0);\n"
56555669
"#endif\n"
56565670
"%s }\n",
5657-
spaces, flow->varname,
56585671
spaces, JDF_OBJECT_ONAME( flow ),
56595672
spaces);
56605673
}

0 commit comments

Comments
 (0)