@@ -437,6 +437,151 @@ typedef struct SE_CreateStreamExecutorParams {
437437#define SE_CREATE_STREAM_EXECUTOR_PARAMS_STRUCT_SIZE \
438438 TF_OFFSET_OF_END(SE_CreateStreamExecutorParams, stream_executor)
439439
440+ typedef struct SP_Allocator {
441+ size_t struct_size;
442+ void* ext; // free-form field set by plugin.
443+
444+ // Whether this platform supports unified memory.
445+ // Unified memory is a single memory address space accessible from any device.
446+ TF_Bool supports_unified_memory;
447+ } SP_Allocator;
448+
449+ #define SP_ALLOCATOR_STRUCT_SIZE \
450+ TF_OFFSET_OF_END(SP_Allocator, supports_unified_memory)
451+
452+ typedef struct SP_AllocatorFns {
453+ size_t struct_size;
454+ void* ext; // reserved for future use.
455+
456+ // Synchronously allocates ` size ` bytes on the underlying platform and returns
457+ // ` SP_DeviceMemoryBase ` representing that allocation. In the case of failure,
458+ // nullptr is returned.
459+ // ` memory_space ` is reserved for a potential future usage and should be set
460+ // to 0.
461+ void (* allocate)(const SP_Device* device, const SP_Allocator* allocator,
462+ uint64_t size, int64_t memory_space,
463+ SP_DeviceMemoryBase* mem);
464+
465+ // Deallocate the device memory previously allocated via this interface.
466+ // Deallocation of a nullptr-representative value is permitted.
467+ void (* deallocate)(const SP_Device* device, const SP_Allocator* allocator,
468+ SP_DeviceMemoryBase* memory);
469+
470+ // Allocates a region of host memory and registers it with the platform API.
471+ // Memory allocated in this manner is required for use in asynchronous memcpy
472+ // operations, such as ` memcpy_dtoh ` .
473+ void* (* host_memory_allocate)(const SP_Device* device,
474+ const SP_Allocator* allocator, uint64_t size);
475+
476+ // Deallocates a region of host memory allocated by ` host_memory_allocate ` .
477+ void (* host_memory_deallocate)(const SP_Device* device,
478+ const SP_Allocator* allocator, void* mem);
479+
480+ // Allocates unified memory space of the given size, if supported. Unified
481+
482+ // memory support should be added by setting ` supports_unified_memory ` field
483+ // in ` SP_Platform ` .
484+ void* (* unified_memory_allocate)(const SP_Device* device,
485+ const SP_Allocator* allocator,
486+ uint64_t bytes);
487+
488+ // Deallocates unified memory space previously allocated with
489+ // ` unified_memory_allocate ` . Unified
490+ // memory support should be added by setting ` supports_unified_memory ` field
491+ // in ` SP_Platform ` .
492+ void (* unified_memory_deallocate)(const SP_Device* device,
493+ const SP_Allocator* allocator,
494+ void* location);
495+
496+ // Fills SP_AllocatorStats with allocator statistics, if it is available.
497+ // If it is not available, return false.
498+ TF_Bool (* get_allocator_stats)(const SP_Device* device,
499+ const SP_Allocator* allocator,
500+ SP_AllocatorStats* stats);
501+
502+ // Fills the underlying device memory usage information, if it is
503+ // available. If it is not available (false is returned), free/total need not
504+ // be initialized.
505+ TF_Bool (* device_memory_usage)(const SP_Device* device,
506+ const SP_Allocator* allocator, int64_t* free,
507+ int64_t* total);
508+ } SP_AllocatorFns;
509+
510+ #define SP_ALLOCATOR_FNS_STRUCT_SIZE \
511+ TF_OFFSET_OF_END(SP_AllocatorFns, device_memory_usage)
512+
513+ typedef struct SP_CustomAllocator {
514+ size_t struct_size;
515+ void* ext; // free-form data set by plugin
516+ } SP_CustomAllocator;
517+
518+ #define SP_CUSTOM_ALLOCATOR_STRUCT_SIZE \
519+ TF_OFFSET_OF_END(SP_CustomAllocator, ext)
520+
521+ typedef struct SP_CustomAllocatorFns {
522+ size_t struct_size;
523+ void* ext; // reserved for future use
524+
525+ // Synchronously allocates ` size ` bytes on the underlying platform and returns
526+ // a pointer to that allocation. In the case of failure,
527+ // nullptr is returned.
528+ void* (* allocate_raw)(const SP_Device* device,
529+ const SP_CustomAllocator* allocator, size_t size,
530+ size_t alignment);
531+
532+ // Deallocate the device memory previously allocated via ` allocate_raw ` .
533+ // Deallocation of a nullptr-representative value is permitted.
534+ void (* deallocate_raw)(const SP_Device* device,
535+ const SP_CustomAllocator* allocator, void* ptr);
536+
537+ // Allocates a region of host memory.
538+ void* (* host_allocate_raw)(const SP_Device* device,
539+ const SP_CustomAllocator* allocator,
540+ uint64_t size);
541+
542+ // Deallocates a region of host memory allocated by ` host_allocate_raw ` .
543+ void (* host_deallocate_raw)(const SP_Device* device,
544+ const SP_CustomAllocator* allocator, void* mem);
545+
546+ // Fills SP_AllocatorStats with allocator statistics, if it is available.
547+ // If it is not available, return false.
548+ TF_Bool (* get_allocator_stats)(const SP_Device* device,
549+ const SP_CustomAllocator* allocator,
550+ SP_AllocatorStats* stats);
551+
552+ // Fills the underlying device memory usage information, if it is
553+ // available. If it is not available (false is returned), free/total need not
554+ // be initialized.
555+ TF_Bool (* device_memory_usage)(const SP_Device* device,
556+ const SP_CustomAllocator* allocator,
557+ int64_t* free, int64_t* total);
558+ } SP_CustomAllocatorFns;
559+
560+ #define SP_CUSTOM_ALLOCATOR_FNS_STRUCT_SIZE \
561+ TF_OFFSET_OF_END(SP_CustomAllocatorFns, device_memory_usage)
562+
563+ typedef struct SE_CreateAllocatorParams {
564+ size_t struct_size;
565+ void* ext; // reserved for future use
566+
567+ SP_Allocator* allocator;
568+ SP_AllocatorFns* allocator_fns;
569+ } SE_CreateAllocatorParams;
570+
571+ #define SE_CREATE_ALLOCATOR_PARAMS_STRUCT_SIZE \
572+ TF_OFFSET_OF_END(SE_CreateAllocatorParams, allocator_fns)
573+
574+ typedef struct SE_CreateCustomAllocatorParams {
575+ size_t struct_size;
576+ void* ext; // reserved for future use
577+
578+ SP_CustomAllocator* custom_allocator;
579+ SP_CustomAllocatorFns* custom_allocator_fns;
580+ } SE_CreateCustomAllocatorParams;
581+
582+ #define SE_CREATE_CUSTOM_ALLOCATOR_PARAMS_STRUCT_SIZE \
583+ TF_OFFSET_OF_END(SE_CreateCustomAllocatorParams, custom_allocator_fns)
584+
440585typedef struct SP_Platform {
441586 size_t struct_size;
442587
@@ -450,15 +595,10 @@ typedef struct SP_Platform {
450595
451596 // Number of visible devices.
452597 size_t visible_device_count;
453-
454- // Whether this platform supports unified memory.
455- // Unified memory is a single memory address space that virtualizes device and
456- // host memory addresses. It is accessible to both the device and host.
457- TF_Bool supports_unified_memory;
458598} SP_Platform;
459599
460600#define SP_PLATFORM_STRUCT_SIZE \
461- TF_OFFSET_OF_END(SP_Platform, supports_unified_memory )
601+ TF_OFFSET_OF_END(SP_Platform, visible_device_count )
462602
463603typedef struct SP_PlatformFns {
464604 size_t struct_size;
@@ -488,11 +628,38 @@ typedef struct SP_PlatformFns {
488628
489629 void (* destroy_timer_fns)(const SP_Platform* platform,
490630 SP_TimerFns* timer_fns);
631+
632+ // Set only one of ` create_allocator ` or ` create_custom_allocator ` functions
633+ // below.
634+
635+ // Callback for creating an allocator that uses default TensorFlow allocation
636+ // strategy (BFC: best-fit with coalescing). For more details, see
637+ // https://cs.opensource.google/tensorflow/tensorflow/+/master:tensorflow/core/common_runtime/bfc_allocator.h .
638+ // If ` create_allocator ` is set, then ` create_custom_allocator ` should * not*
639+ // be set.
640+ void (* create_allocator)(const SP_Platform* platform,
641+ SE_CreateAllocatorParams* params, TF_Status* status);
642+ void (* destroy_allocator)(const SP_Platform* platform,
643+ SP_Allocator* allocator,
644+ SP_AllocatorFns* allocator_fns);
645+
646+ // Callback for creating a custom allocator. Allows using a custom allocation
647+ // strategy.
648+ // If ` create_custom_allocator ` is set, then ` create_allocator ` should * not*
649+ // be set.
650+ // Note: deallocator functions must be set in params.
651+ void (* create_custom_allocator)(const SP_Platform* platform,
652+ SE_CreateCustomAllocatorParams* params,
653+ TF_Status* status);
654+ void (* destroy_custom_allocator)(const SP_Platform* platform,
655+ SP_CustomAllocator* allocator,
656+ SP_CustomAllocatorFns* allocator_fns);
491657} SP_PlatformFns;
492658
493659#define SP_PLATFORM_FNS_STRUCT_SIZE \
494660 TF_OFFSET_OF_END(SP_PlatformFns, destroy_timer_fns)
495661
662+
496663typedef struct SE_PlatformRegistrationParams {
497664 size_t struct_size;
498665 void* ext; // reserved for future use
@@ -584,6 +751,10 @@ void create_timer_fns(const SP_Platform* platform, SP_TimerFns* timer_fns,
584751 timer_fns->nanoseconds = nanoseconds;
585752 ...
586753}
754+ void create_allocator(const SP_Platform* platform, SP_CreateAllocatorParams* params,
755+ TF_Status* status) {
756+ ...
757+ }
587758void destroy_device(const SP_Platform* platform, SP_Device* device) {
588759 // Destroy device handle here.
589760}
@@ -594,6 +765,9 @@ void destroy_stream_executor(const SP_Platform* platform,
594765void destroy_timer_fns(const SP_Platform* platform, SP_TimerFns* timer_fns) {
595766 // Destroy timer functions here.
596767}
768+ void destroy_allocator(const SP_Platform* platform, SP_Allocator* allocator, SP_AllocatorFns* allocator_fns) {
769+ // Clean up allocator here.
770+ }
597771```
598772
599773Define `SE_InitPlugin` that TensorFlow will call when registering the device
@@ -616,6 +790,8 @@ void SE_InitPlugin(SE_PlatformRegistrationParams* params, TF_Status* status) {
616790 params->platform_fns->destroy_stream_executor = destroy_stream_executor;
617791 params->platform_fns->create_timer_fns = create_timer_fns;
618792 params->platform_fns->destroy_timer_fns = destroy_timer_fns;
793+ params->platform_fns->create_allocator = create_allocator;
794+ params->platform_fns->destroy_allocator = destroy_allocator;
619795}
620796```
621797
0 commit comments