mirror of
https://github.com/NGSolve/netgen.git
synced 2024-12-24 21:10:33 +05:00
mem tracing compile time option, simplify by MemoryTracer as member
This commit is contained in:
parent
a394ffedef
commit
a69cdc9000
@ -33,6 +33,7 @@ option( BUILD_STUB_FILES "Build stub files for better autocompletion" ON)
|
||||
option( BUILD_FOR_CONDA "Link python libraries only to executables" OFF)
|
||||
|
||||
option( USE_SUPERBUILD "use ccache" ON)
|
||||
option( TRACE_MEMORY "Enable memory tracing" OFF)
|
||||
|
||||
set(NG_COMPILE_FLAGS "" CACHE STRING "Additional compile flags")
|
||||
|
||||
|
@ -143,6 +143,7 @@ set_vars( NETGEN_CMAKE_ARGS
|
||||
USE_SPDLOG
|
||||
DEBUG_LOG
|
||||
CHECK_RANGE
|
||||
TRACE_MEMORY
|
||||
BUILD_STUB_FILES
|
||||
BUILD_FOR_CONDA
|
||||
NG_COMPILE_FLAGS
|
||||
|
@ -42,6 +42,11 @@ if(CHECK_RANGE OR CMAKE_BUILD_TYPE STREQUAL "Debug" OR CMAKE_BUILD_TYPE STREQUAL
|
||||
target_compile_definitions(ngcore PUBLIC NETGEN_ENABLE_CHECK_RANGE)
|
||||
endif(CHECK_RANGE OR CMAKE_BUILD_TYPE STREQUAL "Debug" OR CMAKE_BUILD_TYPE STREQUAL "DEBUG")
|
||||
|
||||
if(TRACE_MEMORY OR CMAKE_BUILD_TYPE STREQUAL "Debug" OR CMAKE_BUILD_TYPE STREQUAL "DEBUG")
|
||||
target_compile_definitions(ngcore PUBLIC NETGEN_TRACE_MEMORY)
|
||||
endif(TRACE_MEMORY OR CMAKE_BUILD_TYPE STREQUAL "Debug" OR CMAKE_BUILD_TYPE STREQUAL "DEBUG")
|
||||
|
||||
|
||||
if(USE_SPDLOG)
|
||||
include_directories(${SPDLOG_INCLUDE_DIR})
|
||||
install(DIRECTORY ${SPDLOG_INCLUDE_DIR}
|
||||
|
@ -655,7 +655,6 @@ namespace ngcore
|
||||
/// that's the data we have to delete, nullptr for not owning the memory
|
||||
T * mem_to_delete;
|
||||
|
||||
int mem_tracing_id = 0;
|
||||
|
||||
using FlatArray<T,IndexType>::size;
|
||||
using FlatArray<T,IndexType>::data;
|
||||
@ -701,7 +700,7 @@ namespace ngcore
|
||||
|
||||
NETGEN_INLINE Array (Array && a2)
|
||||
{
|
||||
TraceMemorySwap(mem_tracing_id, sizeof(T)*allocsize, a2.mem_tracing_id, sizeof(T)*a2.allocsize);
|
||||
mt.Swap(sizeof(T) * allocsize, a2.mt, sizeof(T) * a2.allocsize);
|
||||
|
||||
size = a2.size;
|
||||
data = a2.data;
|
||||
@ -774,7 +773,7 @@ namespace ngcore
|
||||
NETGEN_INLINE ~Array()
|
||||
{
|
||||
delete [] mem_to_delete;
|
||||
TraceMemoryFree(mem_tracing_id, sizeof(T)*allocsize);
|
||||
mt.Free(sizeof(T)*allocsize);
|
||||
}
|
||||
|
||||
// Only provide this function if T is archivable
|
||||
@ -829,7 +828,7 @@ namespace ngcore
|
||||
NETGEN_INLINE const Array & Assign (size_t asize, LocalHeap & lh)
|
||||
{
|
||||
delete [] mem_to_delete;
|
||||
TraceMemoryFree(mem_tracing_id, sizeof(T)*allocsize);
|
||||
mt.Free(sizeof(T)*allocsize);
|
||||
size = allocsize = asize;
|
||||
data = lh.Alloc<T> (asize);
|
||||
mem_to_delete = nullptr;
|
||||
@ -937,7 +936,7 @@ namespace ngcore
|
||||
NETGEN_INLINE void DeleteAll ()
|
||||
{
|
||||
delete [] mem_to_delete;
|
||||
TraceMemoryFree(mem_tracing_id, sizeof(T)*allocsize);
|
||||
mt.Free(sizeof(T)*allocsize);
|
||||
mem_to_delete = NULL;
|
||||
data = 0;
|
||||
size = allocsize = 0;
|
||||
@ -969,7 +968,7 @@ namespace ngcore
|
||||
/// steal array
|
||||
NETGEN_INLINE Array & operator= (Array && a2)
|
||||
{
|
||||
TraceMemorySwap(mem_tracing_id, sizeof(T)*allocsize, a2.mem_tracing_id, sizeof(T)*a2.allocsize);
|
||||
mt.Swap(sizeof(T)*allocsize, a2.mt, sizeof(T)*a2.allocsize);
|
||||
|
||||
ngcore::Swap (size, a2.size);
|
||||
ngcore::Swap (data, a2.data);
|
||||
@ -1044,7 +1043,7 @@ namespace ngcore
|
||||
|
||||
NETGEN_INLINE void Swap (Array & b)
|
||||
{
|
||||
TraceMemorySwap(mem_tracing_id, sizeof(T)*allocsize, b.mem_tracing_id, sizeof(T)*b.allocsize);
|
||||
mt.Swap(sizeof(T) * allocsize, b.mt, sizeof(T) * b.allocsize);
|
||||
|
||||
ngcore::Swap (size, b.size);
|
||||
ngcore::Swap (data, b.data);
|
||||
@ -1052,21 +1051,18 @@ namespace ngcore
|
||||
ngcore::Swap (mem_to_delete, b.mem_to_delete);
|
||||
}
|
||||
|
||||
NETGEN_INLINE void SetMemoryTracing (int mem_id)
|
||||
NETGEN_INLINE void StartMemoryTracing () const
|
||||
{
|
||||
if(!mem_tracing_id && mem_id)
|
||||
TraceMemoryAlloc(mem_id, sizeof(T)*allocsize);
|
||||
|
||||
if(mem_tracing_id && !mem_id)
|
||||
TraceMemoryFree(mem_tracing_id, sizeof(T)*allocsize);
|
||||
|
||||
mem_tracing_id = mem_id;
|
||||
mt.Alloc(sizeof(T) * allocsize);
|
||||
}
|
||||
|
||||
const MemoryTracer& GetMemoryTracer() const { return mt; }
|
||||
|
||||
private:
|
||||
|
||||
/// resize array, at least to size minsize. copy contents
|
||||
NETGEN_INLINE void ReSize (size_t minsize);
|
||||
MemoryTracer mt;
|
||||
};
|
||||
|
||||
|
||||
@ -1079,7 +1075,7 @@ namespace ngcore
|
||||
|
||||
T * hdata = data;
|
||||
data = new T[nsize];
|
||||
TraceMemoryAlloc(mem_tracing_id, sizeof(T)*nsize );
|
||||
mt.Alloc(sizeof(T) * nsize);
|
||||
|
||||
if (hdata)
|
||||
{
|
||||
@ -1093,7 +1089,7 @@ namespace ngcore
|
||||
for (size_t i = 0; i < mins; i++) data[i] = std::move(hdata[i]);
|
||||
#endif
|
||||
delete [] mem_to_delete;
|
||||
TraceMemoryFree( mem_tracing_id, sizeof(T)*allocsize );
|
||||
mt.Free(sizeof(T) * allocsize);
|
||||
}
|
||||
|
||||
mem_to_delete = data;
|
||||
|
@ -36,10 +36,15 @@ namespace ngcore
|
||||
void BitArray :: SetSize (size_t asize)
|
||||
{
|
||||
if (size == asize) return;
|
||||
if (owns_data) delete [] data;
|
||||
if (owns_data)
|
||||
{
|
||||
delete [] data;
|
||||
mt.Free(Addr(size)+1);
|
||||
}
|
||||
|
||||
size = asize;
|
||||
data = new unsigned char [Addr (size)+1];
|
||||
mt.Alloc(Addr(size)+1);
|
||||
}
|
||||
|
||||
BitArray & BitArray :: Set () throw()
|
||||
|
@ -150,6 +150,14 @@ public:
|
||||
NGCORE_API void DoArchive(Archive& archive);
|
||||
|
||||
NGCORE_API auto * Data() const { return data; }
|
||||
|
||||
const MemoryTracer& GetMemoryTracer() const { return mt; }
|
||||
void StartMemoryTracing() const
|
||||
{
|
||||
if(owns_data)
|
||||
mt.Alloc(Addr(size)+1);
|
||||
}
|
||||
|
||||
private:
|
||||
///
|
||||
unsigned char Mask (size_t i) const
|
||||
@ -159,6 +167,7 @@ private:
|
||||
size_t Addr (size_t i) const
|
||||
{ return (i / CHAR_BIT); }
|
||||
|
||||
MemoryTracer mt;
|
||||
};
|
||||
|
||||
|
||||
|
@ -743,7 +743,9 @@ namespace ngcore
|
||||
}
|
||||
}
|
||||
WriteTimingChart();
|
||||
#ifdef NETGEN_TRACE_MEMORY
|
||||
WriteMemoryChart("");
|
||||
#endif // NETGEN_TRACE_MEMORY
|
||||
paje.WriteEvents();
|
||||
}
|
||||
|
||||
@ -930,6 +932,7 @@ namespace ngcore
|
||||
|
||||
}
|
||||
|
||||
#ifdef NETGEN_TRACE_MEMORY
|
||||
void PajeTrace::WriteMemoryChart( std::string fname )
|
||||
{
|
||||
if(fname=="")
|
||||
@ -1053,6 +1056,7 @@ namespace ngcore
|
||||
WriteSunburstHTML( root, fname, false );
|
||||
|
||||
}
|
||||
#endif // NETGEN_TRACE_MEMORY
|
||||
|
||||
void PajeTrace::WriteTimingChart( )
|
||||
{
|
||||
|
@ -31,7 +31,9 @@ namespace ngcore
|
||||
|
||||
public:
|
||||
NGCORE_API void WriteTimingChart();
|
||||
#ifdef NETGEN_TRACE_MEMORY
|
||||
NGCORE_API void WriteMemoryChart( std::string fname );
|
||||
#endif // NETGEN_TRACE_MEMORY
|
||||
|
||||
// Approximate number of events to trace. Tracing will
|
||||
// be stopped if any thread reaches this number of events
|
||||
|
@ -113,7 +113,9 @@ namespace ngcore
|
||||
|
||||
NgProfiler prof; // NOLINT
|
||||
|
||||
#ifdef NETGEN_TRACE_MEMORY
|
||||
std::vector<std::string> MemoryTracer::names{"root"};
|
||||
std::map< int, std::vector<int> > MemoryTracer::tree;
|
||||
#endif // NETGEN_TRACE_MEMORY
|
||||
|
||||
} // namespace ngcore
|
||||
|
@ -304,45 +304,29 @@ namespace ngcore
|
||||
|
||||
namespace detail
|
||||
{
|
||||
//Type trait to check if a class implements a 'const MemoryTracer& GetMemoryTracer()' function
|
||||
template<typename T>
|
||||
struct has_GetMemoryTracer
|
||||
{
|
||||
private:
|
||||
template<typename T2>
|
||||
static constexpr auto check(T2*) ->
|
||||
typename std::is_same<decltype(std::declval<T2>().GetMemoryTracer()),const MemoryTracer &>::type;
|
||||
template<typename>
|
||||
static constexpr std::false_type check(...);
|
||||
using type = decltype(check<T>(nullptr)); // NOLINT
|
||||
public:
|
||||
static constexpr bool value = type::value;
|
||||
};
|
||||
|
||||
//Type trait to check if a class implements a 'void SetMemoryTacing(int)' function
|
||||
template<typename T>
|
||||
struct has_SetMemoryTracing
|
||||
struct has_StartMemoryTracing
|
||||
{
|
||||
private:
|
||||
template<typename T2>
|
||||
static constexpr auto check(T2*) ->
|
||||
typename std::is_same<decltype(std::declval<T2>().SetMemoryTracing(0)),void>::type;
|
||||
typename std::is_same<decltype(std::declval<T2>().StartMemoryTracing()),void>::type;
|
||||
template<typename>
|
||||
static constexpr std::false_type check(...);
|
||||
using type = decltype(check<T>(nullptr)); // NOLINT
|
||||
public:
|
||||
static constexpr bool value = type::value;
|
||||
};
|
||||
|
||||
|
||||
} // namespace detail
|
||||
|
||||
class MemoryTracer
|
||||
{
|
||||
#ifdef NETGEN_TRACE_MEMORY
|
||||
NGCORE_API static std::vector<std::string> names;
|
||||
NGCORE_API static std::map< int, std::vector<int> > tree;
|
||||
|
||||
static int GetId(std::string name)
|
||||
static int CreateId(const std::string& name)
|
||||
{
|
||||
int id = names.size();
|
||||
names.push_back(name);
|
||||
@ -350,48 +334,73 @@ namespace ngcore
|
||||
std::cerr << "Allocated " << id << " MemoryTracer objects" << std::endl;
|
||||
return id;
|
||||
}
|
||||
|
||||
|
||||
int id;
|
||||
|
||||
public:
|
||||
|
||||
MemoryTracer( std::string name )
|
||||
{
|
||||
id = GetId(name);
|
||||
id = CreateId(name);
|
||||
}
|
||||
|
||||
// not tracing
|
||||
MemoryTracer() : id(0) {}
|
||||
|
||||
template <typename... TRest>
|
||||
MemoryTracer( std::string name, TRest & ... rest )
|
||||
{
|
||||
id = GetId(name);
|
||||
id = CreateId(name);
|
||||
Track(rest...);
|
||||
}
|
||||
|
||||
NETGEN_INLINE void Alloc(size_t size) const
|
||||
{
|
||||
if(id && trace)
|
||||
trace->AllocMemory(id, size);
|
||||
}
|
||||
|
||||
void Free(size_t size) const
|
||||
{
|
||||
if(id && trace)
|
||||
trace->FreeMemory(id, size);
|
||||
}
|
||||
|
||||
void Swap(size_t mysize, MemoryTracer& other, size_t other_size) const
|
||||
{
|
||||
if(!trace || (id == 0 && other.id == 0))
|
||||
return;
|
||||
if(id == 0)
|
||||
return trace->ChangeMemory(other.id, mysize - other_size);
|
||||
if(other.id == 0)
|
||||
return trace->ChangeMemory(id, other_size - mysize);
|
||||
|
||||
// first decrease memory, otherwise have artificial/wrong high peak memory usage
|
||||
if(mysize<other_size)
|
||||
{
|
||||
trace->ChangeMemory(other.id, mysize-other_size);
|
||||
trace->ChangeMemory(id, other_size-mysize);
|
||||
}
|
||||
else
|
||||
{
|
||||
trace->ChangeMemory(id, other_size-mysize);
|
||||
trace->ChangeMemory(other.id, mysize-other_size);
|
||||
}
|
||||
}
|
||||
|
||||
int GetId() const { return id; }
|
||||
|
||||
template <typename T1, typename... TRest>
|
||||
void Track( T1 & obj, std::string name, TRest & ... rest ) const
|
||||
void Track( T1 & obj, const std::string& name, TRest & ... rest ) const
|
||||
{
|
||||
Track(obj, name);
|
||||
Track(rest...);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void Track( T & obj, std::string name ) const
|
||||
void Track( T & obj, const std::string& name ) const
|
||||
{
|
||||
if constexpr(detail::has_SetMemoryTracing<T>::value)
|
||||
{
|
||||
int child_id = GetId(name);
|
||||
tree[id].push_back(child_id);
|
||||
obj.SetMemoryTracing(child_id);
|
||||
}
|
||||
if constexpr(detail::has_GetMemoryTracer<T>::value)
|
||||
{
|
||||
auto & mt = obj.GetMemoryTracer();
|
||||
int child_id = mt.id;
|
||||
if(name!="")
|
||||
names[mt.id] = name;
|
||||
tree[id].push_back(child_id);
|
||||
}
|
||||
obj.GetMemoryTracer().Activate(obj, name);
|
||||
tree[id].push_back(obj.GetMemoryTracer().GetId());
|
||||
}
|
||||
|
||||
static std::string GetName(int id)
|
||||
@ -404,7 +413,20 @@ namespace ngcore
|
||||
return names[id];
|
||||
}
|
||||
|
||||
void SetName(std::string name) const
|
||||
template<typename T>
|
||||
void Activate(T& me, const std::string& name) const
|
||||
{
|
||||
if(!id)
|
||||
{
|
||||
const_cast<MemoryTracer*>(this)->id = CreateId(name);
|
||||
if constexpr(detail::has_StartMemoryTracing<T>::value)
|
||||
me.StartMemoryTracing();
|
||||
}
|
||||
else
|
||||
SetName(name);
|
||||
}
|
||||
|
||||
void SetName(const std::string& name) const
|
||||
{
|
||||
names[id] = name;
|
||||
}
|
||||
@ -412,49 +434,26 @@ namespace ngcore
|
||||
|
||||
static const std::vector<std::string> & GetNames() { return names; }
|
||||
static const std::map<int, std::vector<int>> & GetTree() { return tree; }
|
||||
#else // NETGEN_TRACE_MEMORY
|
||||
public:
|
||||
MemoryTracer() {}
|
||||
MemoryTracer( std::string name ) {}
|
||||
template <typename... TRest>
|
||||
MemoryTracer( std::string name, TRest & ... ) {}
|
||||
|
||||
void Alloc(size_t size) const {}
|
||||
void Free(size_t size) const {}
|
||||
void Swap(...) const {}
|
||||
int GetId() const { return 0; }
|
||||
|
||||
template <typename... TRest>
|
||||
void Track(TRest&...) const {}
|
||||
|
||||
static std::string GetName(int id) { return ""; }
|
||||
std::string GetName() const { return ""; }
|
||||
void SetName(std::string name) const {}
|
||||
#endif // NETGEN_TRACE_MEMORY
|
||||
};
|
||||
|
||||
NETGEN_INLINE void TraceMemoryAlloc( int mem_id, size_t size )
|
||||
{
|
||||
if(mem_id && trace)
|
||||
trace->AllocMemory(mem_id, size);
|
||||
}
|
||||
|
||||
NETGEN_INLINE void TraceMemoryFree( int mem_id, size_t size )
|
||||
{
|
||||
if(mem_id && trace)
|
||||
trace->FreeMemory(mem_id, size);
|
||||
}
|
||||
|
||||
NETGEN_INLINE void TraceMemoryChange( int mem_id, long long size )
|
||||
{
|
||||
if(mem_id && trace)
|
||||
trace->ChangeMemory(mem_id, size);
|
||||
}
|
||||
|
||||
NETGEN_INLINE void TraceMemorySwap( int mem_id, size_t size, int mem_id2, size_t size2 )
|
||||
{
|
||||
if(!trace || (mem_id==0 && mem_id2==0))
|
||||
return;
|
||||
if(mem_id == 0)
|
||||
return trace->ChangeMemory(mem_id2, size-size2);
|
||||
if(mem_id2 == 0)
|
||||
return trace->ChangeMemory(mem_id, size2-size);
|
||||
|
||||
// first decrease memory, otherwise have artificial/wrong high peak memory usage
|
||||
if(size<size2)
|
||||
{
|
||||
trace->ChangeMemory(mem_id2, size-size2);
|
||||
trace->ChangeMemory(mem_id, size2-size);
|
||||
}
|
||||
else
|
||||
{
|
||||
trace->ChangeMemory(mem_id, size2-size);
|
||||
trace->ChangeMemory(mem_id2, size-size2);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace ngcore
|
||||
|
||||
// Helper macro to easily add multiple timers in a function for profiling
|
||||
|
@ -266,7 +266,9 @@ threads : int
|
||||
.def_static("SetTraceThreads", &PajeTrace::SetTraceThreads)
|
||||
.def_static("SetTraceThreadCounter", &PajeTrace::SetTraceThreadCounter)
|
||||
.def_static("SetMaxTracefileSize", &PajeTrace::SetMaxTracefileSize)
|
||||
#ifdef NETGEN_TRACE_MEMORY
|
||||
.def_static("WriteMemoryChart", [](string filename){ if(trace) trace->WriteMemoryChart(filename); }, py::arg("filename")="memory" )
|
||||
#endif // NETGEN_TRACE_MEMORY
|
||||
;
|
||||
|
||||
|
||||
|
@ -159,6 +159,7 @@ namespace ngcore
|
||||
NETGEN_INLINE Table (Table && tab2)
|
||||
: FlatTable<T,IndexType>(0, nullptr, nullptr)
|
||||
{
|
||||
tab2.mt.Free(tab2.GetMemUsage());
|
||||
Swap (size, tab2.size);
|
||||
Swap (index, tab2.index);
|
||||
Swap (data, tab2.data);
|
||||
@ -166,6 +167,7 @@ namespace ngcore
|
||||
|
||||
NETGEN_INLINE Table & operator= (Table && tab2)
|
||||
{
|
||||
mt.Swap(GetMemUsage(), tab2.mt, tab2.GetMemUsage());
|
||||
Swap (size, tab2.size);
|
||||
Swap (index, tab2.index);
|
||||
Swap (data, tab2.data);
|
||||
@ -177,6 +179,7 @@ namespace ngcore
|
||||
/// Delete data
|
||||
NETGEN_INLINE ~Table ()
|
||||
{
|
||||
mt.Free(GetMemUsage());
|
||||
delete [] data;
|
||||
delete [] index;
|
||||
}
|
||||
@ -188,6 +191,16 @@ namespace ngcore
|
||||
NETGEN_INLINE size_t NElements() const { return index[size]; }
|
||||
|
||||
using FlatTable<T,IndexType>::operator[];
|
||||
|
||||
NETGEN_INLINE void StartMemoryTracing (int mem_id)
|
||||
{
|
||||
mt.Alloc(GetMemUsage());
|
||||
}
|
||||
const MemoryTracer& GetMemoryTracer() const { return mt; }
|
||||
|
||||
private:
|
||||
size_t GetMemUsage() const { return size == 0 ? 0 : sizeof(T)*index[size] + sizeof(IndexType) * size+1; }
|
||||
MemoryTracer mt;
|
||||
};
|
||||
|
||||
|
||||
|
@ -90,6 +90,9 @@ namespace netgen
|
||||
|
||||
void GenerateBoundaryLayer(Mesh& mesh, const BoundaryLayerParameters& blp)
|
||||
{
|
||||
static Timer timer("Create Boundarylayers");
|
||||
RegionTimer regt(timer);
|
||||
|
||||
int max_edge_nr = -1;
|
||||
for(const auto& seg : mesh.LineSegments())
|
||||
if(seg.edgenr > max_edge_nr)
|
||||
|
Loading…
Reference in New Issue
Block a user