File: opal_convertor.h

package info (click to toggle)
openmpi 5.0.8-4
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 201,684 kB
  • sloc: ansic: 613,078; makefile: 42,353; sh: 11,194; javascript: 9,244; f90: 7,052; java: 6,404; perl: 5,179; python: 1,859; lex: 740; fortran: 61; cpp: 20; tcl: 12
file content (382 lines) | stat: -rw-r--r-- 15,287 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil -*- */
/*
 * Copyright (c) 2004-2006 The Trustees of Indiana University and Indiana
 *                         University Research and Technology
 *                         Corporation.  All rights reserved.
 * Copyright (c) 2004-2017 The University of Tennessee and The University
 *                         of Tennessee Research Foundation.  All rights
 *                         reserved.
 * Copyright (c) 2004-2006 High Performance Computing Center Stuttgart,
 *                         University of Stuttgart.  All rights reserved.
 * Copyright (c) 2004-2006 The Regents of the University of California.
 *                         All rights reserved.
 * Copyright (c) 2009      Oak Ridge National Labs.  All rights reserved.
 * Copyright (c) 2014      NVIDIA Corporation.  All rights reserved.
 * Copyright (c) 2017-2018 Research Organization for Information Science
 *                         and Technology (RIST).  All rights reserved.
 * Copyright (c) 2017      Intel, Inc. All rights reserved
 * Copyright (c) 2022      Advanced Micro Devices, Inc. All rights reserved.
 * $COPYRIGHT$
 *
 * Additional copyrights may follow
 *
 * $HEADER$
 */

#ifndef OPAL_CONVERTOR_H_HAS_BEEN_INCLUDED
#define OPAL_CONVERTOR_H_HAS_BEEN_INCLUDED

#include "opal_config.h"

#ifdef HAVE_SYS_UIO_H
#    include <sys/uio.h>
#endif

#include "opal/constants.h"
#include "opal/datatype/opal_datatype.h"
#include "opal/prefetch.h"
#include "opal/mca/accelerator/accelerator.h"

BEGIN_C_DECLS
/*
 * CONVERTOR SECTION
 */
/* keep the last 16 bits free for data flags */
#define CONVERTOR_DATATYPE_MASK          0x0000FFFF
#define CONVERTOR_SEND_CONVERSION        0x00010000
#define CONVERTOR_RECV                   0x00020000
#define CONVERTOR_SEND                   0x00040000
#define CONVERTOR_HOMOGENEOUS            0x00080000
#define CONVERTOR_NO_OP                  0x00100000
#define CONVERTOR_WITH_CHECKSUM          0x00200000
#define CONVERTOR_ACCELERATOR            0x00400000
#define CONVERTOR_ACCELERATOR_ASYNC      0x00800000
#define CONVERTOR_TYPE_MASK              0x10FF0000
#define CONVERTOR_STATE_START            0x01000000
#define CONVERTOR_STATE_COMPLETE         0x02000000
#define CONVERTOR_STATE_ALLOC            0x04000000
#define CONVERTOR_COMPLETED              0x08000000
#define CONVERTOR_ACCELERATOR_UNIFIED    0x10000000
#define CONVERTOR_HAS_REMOTE_SIZE        0x20000000
#define CONVERTOR_SKIP_ACCELERATOR_INIT  0x40000000

union dt_elem_desc;
typedef struct opal_convertor_t opal_convertor_t;

typedef int32_t (*convertor_advance_fct_t)(opal_convertor_t *pConvertor, struct iovec *iov,
                                           uint32_t *out_size, size_t *max_data);
typedef void *(*memalloc_fct_t)(size_t *pLength, void *userdata);
typedef void *(*memcpy_fct_t)(void *dest, const void *src, size_t n, opal_convertor_t *pConvertor);

/* The master convertor struct (defined in convertor_internal.h) */
struct opal_convertor_master_t;

struct dt_stack_t {
    int32_t index; /**< index in the element description */
    int16_t type;  /**< the type used for the last pack/unpack (original or OPAL_DATATYPE_UINT1) */
    int16_t padding;
    size_t count;   /**< number of times we still have to do it */
    ptrdiff_t disp; /**< actual displacement depending on the count field */
};
typedef struct dt_stack_t dt_stack_t;

/**
 *
 */
#define DT_STATIC_STACK_SIZE 5 /**< This should be sufficient for most applications */

struct opal_convertor_t {
    opal_object_t super; /**< basic superclass */
    uint32_t remoteArch; /**< the remote architecture */
    uint32_t flags;      /**< the properties of this convertor */
    size_t local_size;   /**< overall length data on local machine, compared to bConverted */
    size_t remote_size;  /**< overall length data on remote machine, compared to bConverted */
    const opal_datatype_t *pDesc;   /**< the datatype description associated with the convertor */
    const dt_type_desc_t *use_desc; /**< the version used by the convertor (normal or optimized) */
    opal_datatype_count_t count;    /**< the total number of full datatype elements */

    /* --- cacheline boundary (64 bytes - if 64bits arch and !OPAL_ENABLE_DEBUG) --- */
    uint32_t stack_size;              /**< size of the allocated stack */
    unsigned char *pBaseBuf;          /**< initial buffer as supplied by the user */
    dt_stack_t *pStack;               /**< the local stack for the actual conversion */
    convertor_advance_fct_t fAdvance; /**< pointer to the pack/unpack functions */

    /* --- cacheline boundary (96 bytes - if 64bits arch and !OPAL_ENABLE_DEBUG) --- */
    struct opal_convertor_master_t *master; /**< the master convertor */

    /* All others fields get modified for every call to pack/unpack functions */
    uint32_t stack_pos;    /**< the actual position on the stack */
    size_t partial_length; /**< amount of data left over from the last unpack */
    size_t bConverted;     /**< # of bytes already converted */

    /* --- cacheline boundary (128 bytes - if 64bits arch and !OPAL_ENABLE_DEBUG) --- */
    uint32_t checksum; /**< checksum computed by pack/unpack operation */
    uint32_t csum_ui1; /**< partial checksum computed by pack/unpack operation */
    size_t csum_ui2;   /**< partial checksum computed by pack/unpack operation */

    /* --- fields are no more aligned on cacheline --- */
    dt_stack_t static_stack[DT_STATIC_STACK_SIZE]; /**< local stack for small datatypes */

    memcpy_fct_t cbmemcpy; /**< memcpy or accelerator memcpy */
    opal_accelerator_stream_t *stream;  /**<Accelerator stream for async copy */
};
OPAL_DECLSPEC OBJ_CLASS_DECLARATION(opal_convertor_t);

/*
 *
 */
static inline uint32_t opal_convertor_get_checksum(opal_convertor_t *convertor)
{
    return convertor->checksum;
}

/*
 *
 */
OPAL_DECLSPEC int32_t opal_convertor_pack(opal_convertor_t *pConv, struct iovec *iov,
                                          uint32_t *out_size, size_t *max_data);

/*
 *
 */
OPAL_DECLSPEC int32_t opal_convertor_unpack(opal_convertor_t *pConv, struct iovec *iov,
                                            uint32_t *out_size, size_t *max_data);

/*
 *
 */
OPAL_DECLSPEC opal_convertor_t *opal_convertor_create(int32_t remote_arch, int32_t mode);

/**
 * The cleanup function will put the convertor in exactly the same state as after a call
 * to opal_convertor_construct. Therefore, all PML can call OBJ_DESTRUCT on the request's
 * convertors without having to call OBJ_CONSTRUCT everytime they grab a new one from the
 * cache. The OBJ_CONSTRUCT on the convertor should be called only on the first creation
 * of a request (not when extracted from the cache).
 */
static inline int opal_convertor_cleanup(opal_convertor_t *convertor)
{
    if (OPAL_UNLIKELY(convertor->stack_size > DT_STATIC_STACK_SIZE)) {
        free(convertor->pStack);
        convertor->pStack = convertor->static_stack;
        convertor->stack_size = DT_STATIC_STACK_SIZE;
    }
    convertor->pDesc = NULL;
    convertor->stack_pos = 0;
    convertor->flags = OPAL_DATATYPE_FLAG_NO_GAPS | CONVERTOR_COMPLETED;

    return OPAL_SUCCESS;
}

/**
 * Return:   0 if no packing is required for sending (the upper layer
 *             can use directly the pointer to the contiguous user
 *             buffer).
 *           1 if data does need to be packed, i.e. heterogeneous peers
 *             (source arch != dest arch) or non contiguous memory
 *             layout.
 */
static inline int32_t opal_convertor_need_buffers(const opal_convertor_t *pConvertor)
{
    if (OPAL_UNLIKELY(0 == (pConvertor->flags & CONVERTOR_HOMOGENEOUS)))
        return 1;
    if (pConvertor->flags & OPAL_DATATYPE_FLAG_NO_GAPS)
        return 0;
    if ((pConvertor->count == 1) && (pConvertor->flags & OPAL_DATATYPE_FLAG_CONTIGUOUS))
        return 0;
    return 1;
}

static inline int32_t opal_convertor_on_device(const opal_convertor_t *pConvertor)
{
    return !!(pConvertor->flags & CONVERTOR_ACCELERATOR);
}

static inline int32_t opal_convertor_on_discrete_device(const opal_convertor_t *pConvertor)
{
    return (CONVERTOR_ACCELERATOR == ((pConvertor->flags & CONVERTOR_ACCELERATOR) |
                                      (pConvertor->flags & CONVERTOR_ACCELERATOR_UNIFIED)));
}

static inline int32_t opal_convertor_on_unified_device(const opal_convertor_t *pConvertor)
{
    return (!!(pConvertor->flags & CONVERTOR_ACCELERATOR) &&
            !!(pConvertor->flags & CONVERTOR_ACCELERATOR_UNIFIED));
}

/**
 * Update the size of the remote datatype representation. The size will
 * depend on the configuration of the master convertor. In homogeneous
 * environments, the local and remote sizes are identical.
 */
size_t opal_convertor_compute_remote_size(opal_convertor_t *pConv);

/**
 * Return the packed size of the memory layout represented by this
 * convertor. This is the size of the buffer that would be needed
 * for the conversion (takes in account the type of the operation,
 * aka pack or unpack, as well as which side is supposed to do the
 * type conversion).
 */
static inline void
opal_convertor_get_packed_size(const opal_convertor_t *pConv, size_t *pSize)
{
    *pSize = pConv->local_size;
    if ((pConv->flags & CONVERTOR_HOMOGENEOUS) ||
        ((pConv->flags & CONVERTOR_SEND) && !(pConv->flags & CONVERTOR_SEND_CONVERSION)) ||
        ((pConv->flags & CONVERTOR_RECV) && (pConv->flags & CONVERTOR_SEND_CONVERSION))) {
        return;
    }
    if (0 == (CONVERTOR_HAS_REMOTE_SIZE & pConv->flags)) {
        assert(!(pConv->flags & CONVERTOR_SEND));
        opal_convertor_compute_remote_size((opal_convertor_t *) pConv);
    }
    *pSize = pConv->remote_size;
}

/**
 * Return the current absolute position of the next pack/unpack. This function is
 * mostly useful for contiguous datatypes, when we need to get the pointer to the
 * contiguous piece of memory.
 */
static inline void opal_convertor_get_current_pointer(const opal_convertor_t *pConv,
                                                      void **position)
{
    unsigned char *base = pConv->pBaseBuf + pConv->bConverted + pConv->pDesc->true_lb;
    *position = (void *) base;
}

static inline void opal_convertor_get_offset_pointer(const opal_convertor_t *pConv, size_t offset,
                                                     void **position)
{
    unsigned char *base = pConv->pBaseBuf + offset + pConv->pDesc->true_lb;
    *position = (void *) base;
}

/*
 *
 */
OPAL_DECLSPEC int32_t opal_convertor_prepare_for_send(opal_convertor_t *convertor,
                                                      const struct opal_datatype_t *datatype,
                                                      size_t count, const void *pUserBuf);

static inline int32_t opal_convertor_copy_and_prepare_for_send(
    const opal_convertor_t *pSrcConv, const struct opal_datatype_t *datatype, size_t count,
    const void *pUserBuf, int32_t flags, opal_convertor_t *convertor)
{
    convertor->remoteArch = pSrcConv->remoteArch;
    convertor->flags = pSrcConv->flags | flags;
    convertor->master = pSrcConv->master;

    return opal_convertor_prepare_for_send(convertor, datatype, count, pUserBuf);
}

/*
 *
 */
OPAL_DECLSPEC int32_t opal_convertor_prepare_for_recv(opal_convertor_t *convertor,
                                                      const struct opal_datatype_t *datatype,
                                                      size_t count, const void *pUserBuf);
static inline int32_t opal_convertor_copy_and_prepare_for_recv(
    const opal_convertor_t *pSrcConv, const struct opal_datatype_t *datatype, size_t count,
    const void *pUserBuf, int32_t flags, opal_convertor_t *convertor)
{
    convertor->remoteArch = pSrcConv->remoteArch;
    convertor->flags = (pSrcConv->flags | flags);
    convertor->master = pSrcConv->master;

    return opal_convertor_prepare_for_recv(convertor, datatype, count, pUserBuf);
}

/*
 * Give access to the raw memory layout based on the datatype.
 */
OPAL_DECLSPEC int32_t opal_convertor_raw(opal_convertor_t *convertor, /* [IN/OUT] */
                                         struct iovec *iov,           /* [IN/OUT] */
                                         uint32_t *iov_count,         /* [IN/OUT] */
                                         size_t *length);             /* [OUT]    */

/*
 * Upper level does not need to call the _nocheck function directly.
 */
OPAL_DECLSPEC int32_t opal_convertor_set_position_nocheck(opal_convertor_t *convertor,
                                                          size_t *position);
static inline int32_t opal_convertor_set_position(opal_convertor_t *convertor, size_t *position)
{
    /*
     * Do not allow the convertor to go outside the data boundaries. This test include
     * the check for datatype with size zero as well as for convertors with a count of zero.
     */
    if (OPAL_UNLIKELY(convertor->local_size <= *position)) {
        convertor->flags |= CONVERTOR_COMPLETED;
        convertor->bConverted = convertor->local_size;
        *position = convertor->bConverted;
        return OPAL_SUCCESS;
    }

    /*
     * If the convertor is already at the correct position we are happy.
     */
    if (OPAL_LIKELY((*position) == convertor->bConverted))
        return OPAL_SUCCESS;

    /* Remove the completed flag if it's already set */
    convertor->flags &= ~CONVERTOR_COMPLETED;

    if ((convertor->flags & OPAL_DATATYPE_FLAG_NO_GAPS) &&
#if defined(CHECKSUM)
        !(convertor->flags & CONVERTOR_WITH_CHECKSUM) &&
#endif /* defined(CHECKSUM) */
        (convertor->flags & (CONVERTOR_SEND | CONVERTOR_HOMOGENEOUS))) {
        /* Contiguous and no checkpoint and no homogeneous unpack */
        convertor->bConverted = *position;
        return OPAL_SUCCESS;
    }

    return opal_convertor_set_position_nocheck(convertor, position);
}

/*
 *
 */
static inline int32_t opal_convertor_personalize(opal_convertor_t *convertor, uint32_t flags,
                                                 size_t *position)
{
    convertor->flags |= flags;

    if (OPAL_UNLIKELY(NULL == position))
        return OPAL_SUCCESS;
    return opal_convertor_set_position(convertor, position);
}

/*
 *
 */
OPAL_DECLSPEC int opal_convertor_clone(const opal_convertor_t *source,
                                       opal_convertor_t *destination, int32_t copy_stack);

static inline int opal_convertor_clone_with_position(const opal_convertor_t *source,
                                                     opal_convertor_t *destination,
                                                     int32_t copy_stack, size_t *position)
{
    (void) opal_convertor_clone(source, destination, copy_stack);
    return opal_convertor_set_position(destination, position);
}

/*
 *
 */
OPAL_DECLSPEC void opal_convertor_dump(opal_convertor_t *convertor);

OPAL_DECLSPEC void opal_datatype_dump_stack(const dt_stack_t *pStack, int stack_pos,
                                            const union dt_elem_desc *pDesc, const char *name);

/*
 *
 */
OPAL_DECLSPEC int opal_convertor_generic_simple_position(opal_convertor_t *pConvertor,
                                                         size_t *position);

END_C_DECLS

#endif /* OPAL_CONVERTOR_H_HAS_BEEN_INCLUDED */