Skip to content

Commit 2179032

Browse files
committed
[NeoMathEngine] CMemoryHandle less memory consumption
Signed-off-by: Kirill Golikov <[email protected]>
1 parent a3e3767 commit 2179032

File tree

8 files changed

+99
-30
lines changed

8 files changed

+99
-30
lines changed

NeoMathEngine/include/NeoMathEngine/MemoryHandle.h

Lines changed: 53 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* Copyright © 2017-2020 ABBYY Production LLC
1+
/* Copyright © 2017-2023 ABBYY
22
33
Licensed under the Apache License, Version 2.0 (the "License");
44
you may not use this file except in compliance with the License.
@@ -16,6 +16,7 @@ limitations under the License.
1616
#pragma once
1717

1818
#include <NeoMathEngine/NeoMathEngineDefs.h>
19+
#include <NeoMathEngine/NeoMathEngineException.h>
1920
#include <cstddef>
2021
#include <type_traits>
2122

@@ -24,47 +25,77 @@ namespace NeoML {
2425
class IMathEngine;
2526
class CMemoryHandleInternal;
2627

28+
// Get pointer to IMathEngine by the given CurrentEntity
29+
inline IMathEngine* GetMathEngineByIndex( size_t currentEntity );
30+
// Get current entity from the given pointer to IMathEngine
31+
inline size_t GetIndexOfMathEngine( const IMathEngine* mathEngine );
32+
2733
// Wraps the pointer to memory allocated by a math engine
2834
class NEOMATHENGINE_API CMemoryHandle {
35+
private:
36+
#if FINE_PLATFORM( FINE_64_BIT )
37+
static constexpr int MathEngineCountWidth = 10; // compress to bitfield
38+
static constexpr int MathEngineCountShift = ( sizeof( size_t ) * 8 /*bits*/ ) - MathEngineCountWidth;
39+
static constexpr size_t MathEngineEntityInvalid = ( ( size_t( 1 ) << MathEngineCountWidth ) - 1 );
40+
static constexpr size_t MathEngineMaxOffset = size_t( 1 ) << MathEngineCountShift;
41+
#else // FINE_32_BIT
42+
// only for bitfield compiles correct. no compress
43+
static constexpr int MathEngineCountWidth = sizeof( size_t ) * 8;
44+
static constexpr int MathEngineCountShift = sizeof( size_t ) * 8;
45+
static constexpr size_t MathEngineEntityInvalid = size_t( -1 );
46+
#endif // FINE_32_BIT
47+
2948
public:
30-
CMemoryHandle() : mathEngine( 0 ), object( 0 ), offset( 0 ) {}
31-
CMemoryHandle( const CMemoryHandle& other ) : mathEngine( other.mathEngine ), object( other.object ), offset( other.offset ) {}
49+
// Any possible number of all mathEngines
50+
static constexpr int MaxMathEngineEntities = 1024;
51+
52+
CMemoryHandle() : object( nullptr ), offset( 0 ), entity( MathEngineEntityInvalid ) {}
53+
CMemoryHandle( const CMemoryHandle& other ) : object( other.object ), offset( other.offset ), entity( other.entity ) {}
3254

3355
CMemoryHandle& operator=( const CMemoryHandle& other )
3456
{
35-
mathEngine = other.mathEngine;
36-
object = other.object;
37-
offset = other.offset;
57+
if( this != &other ) {
58+
object = other.object;
59+
offset = other.offset;
60+
entity = other.entity;
61+
}
3862
return *this;
3963
}
4064

4165
bool operator==( const CMemoryHandle& other ) const
42-
{
43-
return mathEngine == other.mathEngine && object == other.object && offset == other.offset;
44-
}
66+
{ return object == other.object && offset == other.offset && entity == other.entity; }
4567

46-
bool operator!=( const CMemoryHandle& other ) const
47-
{
48-
return !operator==( other );
49-
}
68+
bool operator!=( const CMemoryHandle& other ) const { return !operator==( other ); }
5069

51-
bool IsNull() const
52-
{
53-
return mathEngine == 0 && object == 0 && offset == 0;
54-
}
70+
bool IsNull() const { return object == nullptr && offset == 0 && entity == MathEngineEntityInvalid; }
5571

56-
IMathEngine* GetMathEngine() const { return mathEngine; }
72+
IMathEngine* GetMathEngine() const { return GetMathEngineByIndex( entity ); }
5773

5874
protected:
59-
IMathEngine* mathEngine; // the math engine
75+
// struct of (16 bytes size for x64 and arm-x64) and (12 bytes size for x86 and arm-x32)
6076
const void* object; // the base object
61-
std::ptrdiff_t offset; // the offset in the base object, in bytes
77+
size_t offset : MathEngineCountShift; // (x64) the less significant bits of size_t stores offset in the base object, in bytes
78+
size_t entity : MathEngineCountWidth; // (x64) the most significant bits of size_t stores the number of IMathEngine entity
6279

6380
friend class CMemoryHandleInternal;
6481

65-
explicit CMemoryHandle( IMathEngine* _mathEngine, const void* _object, ptrdiff_t _offset ) : mathEngine( _mathEngine ), object( _object ), offset( _offset ) {}
82+
explicit CMemoryHandle( IMathEngine* _mathEngine, const void* _object, ptrdiff_t _offset ) :
83+
CMemoryHandle( _object , _offset, GetIndexOfMathEngine( _mathEngine ) )
84+
{}
85+
86+
CMemoryHandle CopyMemoryHandle( ptrdiff_t shift ) const { return CMemoryHandle( object, offset + shift, entity ); }
6687

67-
CMemoryHandle CopyMemoryHandle( ptrdiff_t shift ) const { return CMemoryHandle( mathEngine, object, offset + shift ); }
88+
private:
89+
explicit CMemoryHandle( const void* _object, ptrdiff_t _offset, size_t _entity ) :
90+
object( _object ), offset( _offset ), entity( _entity )
91+
{
92+
#if FINE_PLATFORM( FINE_64_BIT )
93+
static_assert( MaxMathEngineEntities == ( 1 << MathEngineCountWidth ), "Invalid MaxMathEngineEntities" );
94+
// Checks that the most significant bits do not interfere the result
95+
ASSERT_EXPR( 0 <= _offset && size_t( _offset ) < MathEngineMaxOffset );
96+
#endif // FINE_64_BIT
97+
ASSERT_EXPR( _entity < MaxMathEngineEntities );
98+
}
6899
};
69100

70101
//------------------------------------------------------------------------------------------------------------

NeoMathEngine/include/NeoMathEngine/MemoryHandle.inl

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* Copyright © 2017-2020 ABBYY Production LLC
1+
/* Copyright © 2017-2023 ABBYY
22
33
Licensed under the Apache License, Version 2.0 (the "License");
44
you may not use this file except in compliance with the License.
@@ -23,30 +23,30 @@ template<class T>
2323
inline void CTypedMemoryHandle<T>::SetValueAt( int index, T value ) const
2424
{
2525
CTypedMemoryHandle<T> result = *this + index;
26-
mathEngine->DataExchangeRaw( result, &value, sizeof( T ) );
26+
GetMathEngine()->DataExchangeRaw( result, &value, sizeof( T ) );
2727
}
2828

2929
template<class T>
3030
inline T CTypedMemoryHandle<T>::GetValueAt( int index ) const
3131
{
3232
char result[sizeof(T)];
3333
CTypedMemoryHandle<T> source = *this + index;
34-
mathEngine->DataExchangeRaw( result, source, sizeof( T ) );
34+
GetMathEngine()->DataExchangeRaw( result, source, sizeof( T ) );
3535
T* value = reinterpret_cast<T*>( &result );
3636
return *value;
3737
}
3838

3939
template<class T>
4040
inline void CTypedMemoryHandle<T>::SetValue( T value ) const
4141
{
42-
mathEngine->DataExchangeRaw( *this, &value, sizeof( T ) );
42+
GetMathEngine()->DataExchangeRaw( *this, &value, sizeof( T ) );
4343
}
4444

4545
template<class T>
4646
inline T CTypedMemoryHandle<T>::GetValue() const
4747
{
4848
char result[sizeof(T)];
49-
mathEngine->DataExchangeRaw( result, *this, sizeof( T ) );
49+
GetMathEngine()->DataExchangeRaw( result, *this, sizeof( T ) );
5050
T* value = reinterpret_cast<T*>( &result );
5151
return *value;
5252
}

NeoMathEngine/include/NeoMathEngine/NeoMathEngine.h

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1230,15 +1230,46 @@ class NEOMATHENGINE_API IMathEngine : public IDnnEngine {
12301230
// This object should be destroyed using the standard delete operator after use.
12311231
virtual IPerformanceCounters* CreatePerformanceCounters( bool isTimeOnly = false ) const = 0;
12321232

1233+
// Methods group for the DnnDistributed execution only
12331234
virtual CMathEngineDistributedInfo GetDistributedInfo() { return CMathEngineDistributedInfo(); }
12341235
virtual void AllReduce( const CFloatHandle& handle, int size ) = 0;
12351236
virtual void Broadcast( const CFloatHandle& handle, int size, int root ) = 0;
12361237
virtual void AbortDistributed() {};
12371238
virtual bool IsDistributed() { return false; }
1239+
1240+
// Get CurrentEntity for IMathEngine
1241+
size_t GetCurrentEntity() const { return CurrentEntity; }
1242+
1243+
protected:
1244+
// All below is need to avoid excess (8 bytes) field in each CMemoryHandler
1245+
1246+
// Special constructor
1247+
explicit IMathEngine( int/*cannot be no call*/ ) :
1248+
CurrentEntity( ++MathEngineEntitiesNumerator )
1249+
{
1250+
ASSERT_EXPR( CurrentEntity < CMemoryHandle::MaxMathEngineEntities );
1251+
MathEngineEntitiesArray[CurrentEntity] = this;
1252+
}
1253+
1254+
// Generation for indices of all IMathEngine entities,
1255+
// Incremets evey moment new MathEngine created to generate its CurrentEntity value.
1256+
static size_t MathEngineEntitiesNumerator;
1257+
// Array for pointers to all entities of IMathEngine
1258+
// No cache ping-pong, because pointers are created once and never changes
1259+
static IMathEngine* MathEngineEntitiesArray[CMemoryHandle::MaxMathEngineEntities];
1260+
// Index of the current IMathEngine entity
1261+
const size_t CurrentEntity;
1262+
1263+
friend IMathEngine* GetMathEngineByIndex( size_t currentEntity );
12381264
};
12391265

12401266
//------------------------------------------------------------------------------------------------------------
12411267

1268+
// Get pointer to IMathEngine by the given CurrentEntity
1269+
inline IMathEngine* GetMathEngineByIndex( size_t currentEntity ) { return IMathEngine::MathEngineEntitiesArray[currentEntity]; }
1270+
// Get current entity from the given pointer to IMathEngine
1271+
inline size_t GetIndexOfMathEngine( const IMathEngine* mathEngine ) { return mathEngine->GetCurrentEntity(); }
1272+
12421273
// Creates a math engine that uses a CPU for calculations.
12431274
// You should call SetMathEngineExceptionHandler() before this call.
12441275
// the default value is 0, which means as many memory as the system has.

NeoMathEngine/src/CPU/CpuMathEngine.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ int NEOMATHENGINE_API FloatAlignment = CCPUInfo::DefineFloatAlignment();
5353
CCpuMathEngine::CCpuMathEngine( size_t _memoryLimit,
5454
std::shared_ptr<CMultiThreadDistributedCommunicator> communicator,
5555
const CMathEngineDistributedInfo& distributedInfo ) :
56+
IMathEngine( 0 ),
5657
floatAlignment( FloatAlignment ),
5758
memoryAlignment( floatAlignment * sizeof(float) ),
5859
communicator( communicator ),

NeoMathEngine/src/GPU/CUDA/CudaMathEngine.cu

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* Copyright © 2017-2020 ABBYY Production LLC
1+
/* Copyright © 2017-2023 ABBYY
22
33
Licensed under the Apache License, Version 2.0 (the "License");
44
you may not use this file except in compliance with the License.
@@ -41,6 +41,7 @@ const int CudaMemoryAlignment = 4;
4141
//------------------------------------------------------------------------------------------------------------
4242

4343
CCudaMathEngine::CCudaMathEngine( const CCusparse* _cusparse, const CCublas* _cublas, std::unique_ptr<CCudaDevice>& _device, int flags ) :
44+
IMathEngine( 0 ),
4445
loader( CDllLoader::CUDA_DLL ),
4546
cusparse( _cusparse ),
4647
cublas( _cublas ),

NeoMathEngine/src/GPU/Metal/MetalMathEngine.mm

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* Copyright © 2017-2020 ABBYY Production LLC
1+
/* Copyright © 2017-2023 ABBYY
22
33
Licensed under the Apache License, Version 2.0 (the "License");
44
you may not use this file except in compliance with the License.
@@ -73,6 +73,7 @@ bool LoadMetalEngineInfo( CMathEngineInfo& info )
7373
const int MetalMemoryAlignment = 16;
7474

7575
CMetalMathEngine::CMetalMathEngine( size_t memoryLimit ) :
76+
IMathEngine( 0 ),
7677
queue( new CMetalCommandQueue() ),
7778
memoryPool( new CMemoryPool( MIN( memoryLimit == 0 ? SIZE_MAX : memoryLimit, defineMemoryLimit() ), this, false ) ),
7879
deviceStackAllocator( new CDeviceStackAllocator( *memoryPool, MetalMemoryAlignment ) ),

NeoMathEngine/src/GPU/Vulkan/VulkanMathEngine.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* Copyright © 2017-2020 ABBYY Production LLC
1+
/* Copyright © 2017-2023 ABBYY
22
33
Licensed under the Apache License, Version 2.0 (the "License");
44
you may not use this file except in compliance with the License.
@@ -71,6 +71,7 @@ bool LoadVulkanEngineInfo( const CVulkanDll& dll, std::vector< CMathEngineInfo,
7171
constexpr int VulkanMemoryAlignment = 16;
7272

7373
CVulkanMathEngine::CVulkanMathEngine( std::unique_ptr<const CVulkanDevice>& _device, size_t memoryLimit ) :
74+
IMathEngine( 0 ),
7475
dllLoader( CDllLoader::VULKAN_DLL ),
7576
device( std::move( _device ) ),
7677
tmpImages( TVI_Count, nullptr )

NeoMathEngine/src/MathEngine.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,9 @@ IMathEngineExceptionHandler* GetMathEngineExceptionHandler()
218218

219219
//------------------------------------------------------------------------------------------------------------
220220

221+
size_t IMathEngine::MathEngineEntitiesNumerator = 0;
222+
IMathEngine* IMathEngine::MathEngineEntitiesArray[CMemoryHandle::MaxMathEngineEntities]{};
223+
221224
IMathEngine* CreateCpuMathEngine( size_t memoryLimit )
222225
{
223226
return new CCpuMathEngine( memoryLimit );

0 commit comments

Comments
 (0)