From c7cedfb7a7070b2264c4af7dd2e4c1365b5cfa09 Mon Sep 17 00:00:00 2001 From: Jeff Hammond Date: Tue, 20 Jul 2021 12:12:48 +0300 Subject: [PATCH 1/5] add MA count/uncount heap API NWChem is using Fortran allocatable now and it is good for MA stats to know about this to keep an accurate account of maximum memory use. Signed-off-by: Jeff Hammond --- ma/ma.c | 152 +++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 151 insertions(+), 1 deletion(-) diff --git a/ma/ma.c b/ma/ma.c index 52fa4b727..e51399b71 100644 --- a/ma/ma.c +++ b/ma/ma.c @@ -430,7 +430,9 @@ typedef enum FID_MA_sizeof_overhead, FID_MA_summarize_allocated_blocks, FID_MA_trace, - FID_MA_verify_allocator_stuff + FID_MA_verify_allocator_stuff, + FID_MA_count_heap, + FID_MA_uncount_heap } FID; /* MA usage statistics */ @@ -3683,3 +3685,151 @@ public Boolean MA_verify_allocator_stuff() #endif /* VERIFY */ } + +/* ------------------------------------------------------------------------- */ +/* + * Add the size of an _external_ allocation (i.e. Fortran allocate) to MA stats + * to allow applications (e.g. NWChem) to accurately track their memory + * consumption. + * + * Return MA_TRUE upon success, or MA_FALSE upon failure. + */ +/* ------------------------------------------------------------------------- */ + +public Boolean MA_count_heap( + Integer datatype, /* of elements in the block */ + Integer nelem, /* # of elements in the block */ + const char * name /* assigned to this block by client */ + ) +{ + ulongi nbytes; + +#ifdef STATS + ma_stats.calls[(int)FID_MA_count_heap]++; +#endif /* STATS */ + + if (ma_trace) + (void)printf("MA: counting '%s' (%d)\n", name, (int)nelem); + + /* verify initialization */ + if (!ma_initialized) + { + (void)sprintf(ma_ebuf, + "block '%s', MA not yet initialized", + name); + ma_error(EL_Nonfatal, ET_External, "MA_count_heap", ma_ebuf); + return MA_FALSE; + } + + /* verify datatype */ + if (!mt_valid(datatype)) + { + (void)sprintf(ma_ebuf, + "block '%s', invalid datatype: %ld", + name, (size_t)datatype); + ma_error(EL_Nonfatal, ET_External, "MA_count_heap", ma_ebuf); + return MA_FALSE; + } + + /* verify nelem */ + if (nelem < 0) + { + (void)sprintf(ma_ebuf, + "block '%s', invalid nelem: %ld", + name, (size_t)nelem); + ma_error(EL_Nonfatal, ET_External, "MA_count_heap", ma_ebuf); + return MA_FALSE; + } + + /* convert datatype to internal (index-suitable) value */ + datatype = mt_import(datatype); + + /* compute the number of bytes in an element */ + nbytes = ma_sizeof[datatype]; + + /* total number of bytes */ + nbytes *= nelem; + +#ifdef STATS + ma_stats.hblocks++; + ma_stats.hblocks_max = max(ma_stats.hblocks, ma_stats.hblocks_max); + ma_stats.hbytes += nbytes; + ma_stats.hbytes_max = max(ma_stats.hbytes, ma_stats.hbytes_max); +#endif /* STATS */ + + return MA_TRUE; + +} + +/* ------------------------------------------------------------------------- */ +/* + * Subtract the size of an _external_ allocation (i.e. Fortran allocate) to MA stats + * to allow applications (e.g. NWChem) to accurately track their memory + * consumption. + * + * Return MA_TRUE upon success, or MA_FALSE upon failure. + */ +/* ------------------------------------------------------------------------- */ + +public Boolean MA_uncount_heap( + Integer datatype, /* of elements in the block */ + Integer nelem, /* # of elements in the block */ + const char * name /* assigned to this block by client */ + ) +{ + ulongi nbytes; + +#ifdef STATS + ma_stats.calls[(int)FID_MA_uncount_heap]++; +#endif /* STATS */ + + if (ma_trace) + (void)printf("MA: uncounting '%s' (%d)\n", name, (int)nelem); + + /* verify initialization */ + if (!ma_initialized) + { + (void)sprintf(ma_ebuf, + "block '%s', MA not yet initialized", + name); + ma_error(EL_Nonfatal, ET_External, "MA_uncount_heap", ma_ebuf); + return MA_FALSE; + } + + /* verify datatype */ + if (!mt_valid(datatype)) + { + (void)sprintf(ma_ebuf, + "block '%s', invalid datatype: %ld", + name, (size_t)datatype); + ma_error(EL_Nonfatal, ET_External, "MA_uncount_heap", ma_ebuf); + return MA_FALSE; + } + + /* verify nelem */ + if (nelem < 0) + { + (void)sprintf(ma_ebuf, + "block '%s', invalid nelem: %ld", + name, (size_t)nelem); + ma_error(EL_Nonfatal, ET_External, "MA_uncount_heap", ma_ebuf); + return MA_FALSE; + } + + /* convert datatype to internal (index-suitable) value */ + datatype = mt_import(datatype); + + /* compute the number of bytes in an element */ + nbytes = ma_sizeof[datatype]; + + /* total number of bytes */ + nbytes *= nelem; + +#ifdef STATS + ma_stats.hblocks--; + ma_stats.hbytes -= nbytes; +#endif /* STATS */ + + return MA_TRUE; + +} From eccbe6c87fe49faa0a1954388b536dfaa2cb0042 Mon Sep 17 00:00:00 2001 From: Jeff Hammond Date: Tue, 20 Jul 2021 12:41:14 +0300 Subject: [PATCH 2/5] remove name argument from count/uncount routines --- ma/ma.c | 36 ++++++++++-------------------------- 1 file changed, 10 insertions(+), 26 deletions(-) diff --git a/ma/ma.c b/ma/ma.c index e51399b71..c1775a84d 100644 --- a/ma/ma.c +++ b/ma/ma.c @@ -3698,8 +3698,7 @@ public Boolean MA_verify_allocator_stuff() public Boolean MA_count_heap( Integer datatype, /* of elements in the block */ - Integer nelem, /* # of elements in the block */ - const char * name /* assigned to this block by client */ + Integer nelem /* # of elements in the block */ ) { ulongi nbytes; @@ -3709,14 +3708,12 @@ public Boolean MA_count_heap( #endif /* STATS */ if (ma_trace) - (void)printf("MA: counting '%s' (%d)\n", name, (int)nelem); + (void)printf("MA: counting (%d)\n", (int)nelem); /* verify initialization */ if (!ma_initialized) { - (void)sprintf(ma_ebuf, - "block '%s', MA not yet initialized", - name); + (void)sprintf(ma_ebuf, "MA not yet initialized"); ma_error(EL_Nonfatal, ET_External, "MA_count_heap", ma_ebuf); return MA_FALSE; } @@ -3724,9 +3721,7 @@ public Boolean MA_count_heap( /* verify datatype */ if (!mt_valid(datatype)) { - (void)sprintf(ma_ebuf, - "block '%s', invalid datatype: %ld", - name, (size_t)datatype); + (void)sprintf(ma_ebuf, "invalid datatype: %ld", (size_t)datatype); ma_error(EL_Nonfatal, ET_External, "MA_count_heap", ma_ebuf); return MA_FALSE; } @@ -3734,9 +3729,7 @@ public Boolean MA_count_heap( /* verify nelem */ if (nelem < 0) { - (void)sprintf(ma_ebuf, - "block '%s', invalid nelem: %ld", - name, (size_t)nelem); + (void)sprintf(ma_ebuf, "invalid nelem: %ld", (size_t)nelem); ma_error(EL_Nonfatal, ET_External, "MA_count_heap", ma_ebuf); return MA_FALSE; } @@ -3758,7 +3751,6 @@ public Boolean MA_count_heap( #endif /* STATS */ return MA_TRUE; - } /* ------------------------------------------------------------------------- */ @@ -3773,8 +3765,7 @@ public Boolean MA_count_heap( public Boolean MA_uncount_heap( Integer datatype, /* of elements in the block */ - Integer nelem, /* # of elements in the block */ - const char * name /* assigned to this block by client */ + Integer nelem /* # of elements in the block */ ) { ulongi nbytes; @@ -3784,14 +3775,12 @@ public Boolean MA_uncount_heap( #endif /* STATS */ if (ma_trace) - (void)printf("MA: uncounting '%s' (%d)\n", name, (int)nelem); + (void)printf("MA: uncounting (%d)\n", (int)nelem); /* verify initialization */ if (!ma_initialized) { - (void)sprintf(ma_ebuf, - "block '%s', MA not yet initialized", - name); + (void)sprintf(ma_ebuf, "MA not yet initialized"); ma_error(EL_Nonfatal, ET_External, "MA_uncount_heap", ma_ebuf); return MA_FALSE; } @@ -3799,9 +3788,7 @@ public Boolean MA_uncount_heap( /* verify datatype */ if (!mt_valid(datatype)) { - (void)sprintf(ma_ebuf, - "block '%s', invalid datatype: %ld", - name, (size_t)datatype); + (void)sprintf(ma_ebuf, "invalid datatype: %ld", (size_t)datatype); ma_error(EL_Nonfatal, ET_External, "MA_uncount_heap", ma_ebuf); return MA_FALSE; } @@ -3809,9 +3796,7 @@ public Boolean MA_uncount_heap( /* verify nelem */ if (nelem < 0) { - (void)sprintf(ma_ebuf, - "block '%s', invalid nelem: %ld", - name, (size_t)nelem); + (void)sprintf(ma_ebuf, "invalid nelem: %ld", (size_t)nelem); ma_error(EL_Nonfatal, ET_External, "MA_uncount_heap", ma_ebuf); return MA_FALSE; } @@ -3831,5 +3816,4 @@ public Boolean MA_uncount_heap( #endif /* STATS */ return MA_TRUE; - } From 66e81375f5e311441aae3719a122f0d92c9568df Mon Sep 17 00:00:00 2001 From: Jeff Hammond Date: Tue, 20 Jul 2021 12:43:29 +0300 Subject: [PATCH 3/5] add f2c for count/uncount Signed-off-by: Jeff Hammond --- ma/f2c.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/ma/f2c.c b/ma/f2c.c index 346a5d68a..7fe3193b8 100644 --- a/ma/f2c.c +++ b/ma/f2c.c @@ -335,3 +335,17 @@ public Boolean FATR f2c_verify_allocator_stuff_() { return MA_verify_allocator_stuff(); } + +public Boolean FATR f2c_count_heap_(datatype, nelem) + Integer *datatype; + Integer *nelem; +{ + return MA_count_heap(*datatype, *nelem); +} + +public Boolean FATR f2c_uncount_heap_(datatype, nelem) + Integer *datatype; + Integer *nelem; +{ + return MA_uncount_heap(*datatype, *nelem); +} From ca7c7f3ebe7dfe0db7f020ccfac90d0b0b60a685 Mon Sep 17 00:00:00 2001 From: Jeff Hammond Date: Tue, 20 Jul 2021 13:01:33 +0300 Subject: [PATCH 4/5] add various Fortran to C things for count/uncount Signed-off-by: Jeff Hammond --- ma/ma.h | 2 ++ ma/maf.F | 42 ++++++++++++++++++++++++++++++++++++++++++ ma/maf2c.fh | 4 ++++ 3 files changed, 48 insertions(+) diff --git a/ma/ma.h b/ma/ma.h index e54a8271a..63c914923 100644 --- a/ma/ma.h +++ b/ma/ma.h @@ -50,5 +50,7 @@ extern void MAi_summarize_allocated_blocks(int index_base); #define f2c_trace_ F77_FUNC_(f2c_trace,F2C_TRACE) #define f2c_verify_allocator_stuff_ F77_FUNC_(f2c_verify_allocator_stuff,F2C_VERIFY_ALLOCATOR_STUFF) #define ma_set_sizes_ F77_FUNC_(ma_set_sizes,MA_SET_SIZES) +#define f2c_count_heap_ F77_FUNC_(f2c_count_heap,F2C_COUNT_HEAP) +#define f2c_uncount_heap_ F77_FUNC_(f2c_uncount_heap,F2C_UNCOUNT_HEAP) #endif /* _ma_h */ diff --git a/ma/maf.F b/ma/maf.F index 871f5d3da..e15eb632b 100644 --- a/ma/maf.F +++ b/ma/maf.F @@ -675,4 +675,46 @@ logical function MA_verify_allocator_stuff () return end +c --------------------------------------------------------------- c +c --------------------------------------------------------------- c + + logical function MA_count_heap (datatype, nelem) + + implicit none + + integer datatype + integer nelem + +#include "maf2c.fh" + + if (f2c_count_heap(datatype, nelem) .eq. MA_TRUE) then + MA_count_heap = .true. + else + MA_count_heap = .false. + endif + + return + end + +c --------------------------------------------------------------- c +c --------------------------------------------------------------- c + + logical function MA_uncount_heap (datatype, nelem) + + implicit none + + integer datatype + integer nelem + +#include "maf2c.fh" + + if (f2c_uncount_heap(datatype, nelem) .eq. MA_TRUE) then + MA_uncount_heap = .true. + else + MA_uncount_heap = .false. + endif + + return + end + #undef MAF_INTERNAL diff --git a/ma/maf2c.fh b/ma/maf2c.fh index 425dd951a..4c139315d 100644 --- a/ma/maf2c.fh +++ b/ma/maf2c.fh @@ -56,6 +56,8 @@ c void f2c_print_stats c void f2c_summarize_allocated_blocks c void f2c_trace integer f2c_verify_allocator_stuff + integer f2c_count_heap + integer f2c_uncount_heap external f2c_alloc_get external f2c_allocate_heap @@ -89,3 +91,5 @@ c void f2c_trace external f2c_summarize_allocated_blocks external f2c_trace external f2c_verify_allocator_stuff + external f2c_count_heap + external f2c_uncount_heap From 2586ec0d5149d44839894042b375af5b87ab45e0 Mon Sep 17 00:00:00 2001 From: Jeff Hammond Date: Tue, 20 Jul 2021 13:43:31 +0300 Subject: [PATCH 5/5] fix compilation errors Signed-off-by: Jeff Hammond --- ma/ma.c | 4 ++-- ma/macdecls.h | 7 +++++++ 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/ma/ma.c b/ma/ma.c index c1775a84d..6f93edf44 100644 --- a/ma/ma.c +++ b/ma/ma.c @@ -430,9 +430,9 @@ typedef enum FID_MA_sizeof_overhead, FID_MA_summarize_allocated_blocks, FID_MA_trace, - FID_MA_verify_allocator_stuff, FID_MA_count_heap, - FID_MA_uncount_heap + FID_MA_uncount_heap, + FID_MA_verify_allocator_stuff } FID; /* MA usage statistics */ diff --git a/ma/macdecls.h b/ma/macdecls.h index 1716e46a8..068b3324e 100644 --- a/ma/macdecls.h +++ b/ma/macdecls.h @@ -102,6 +102,13 @@ extern void MA_trace(Boolean value); extern Boolean MA_verify_allocator_stuff(); extern void MA_set_error_callback(void(*func)()); +extern Boolean MA_count_heap( + Integer datatype, /**< of elements in this block */ + Integer nelem /**< # of elements in this block */); +extern Boolean MA_uncount_heap( + Integer datatype, /**< of elements in this block */ + Integer nelem /**< # of elements in this block */); + extern void ma_set_error_callback(); /**