Skip to content

Commit e968294

Browse files
committed
THAlloc trigger GC when heap size exceeds soft max
1 parent f8b4ada commit e968294

File tree

2 files changed

+65
-4
lines changed

2 files changed

+65
-4
lines changed

THGeneral.c

Lines changed: 63 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,14 @@
33
#ifndef TH_HAVE_THREAD
44
#define __thread
55
#endif
6+
7+
#if defined(TH_DISABLE_HEAP_TRACKING)
8+
#elif (defined(__unix) || defined(_WIN32))
9+
#include <malloc.h>
10+
#elif defined(__APPLE__)
11+
#include <malloc/malloc.h>
12+
#endif
13+
614
/* Torch Error Handling */
715
static void defaultTorchErrorHandlerFunction(const char *msg, void *data)
816
{
@@ -13,9 +21,6 @@ static void defaultTorchErrorHandlerFunction(const char *msg, void *data)
1321
static __thread void (*torchErrorHandlerFunction)(const char *msg, void *data) = defaultTorchErrorHandlerFunction;
1422
static __thread void *torchErrorHandlerData;
1523

16-
static __thread void (*torchGCFunction)(void *data) = NULL;
17-
static __thread void *torchGCData;
18-
1924
void _THError(const char *file, const int line, const char *fmt, ...)
2025
{
2126
char msg[2048];
@@ -94,13 +99,62 @@ void THSetArgErrorHandler( void (*torchArgErrorHandlerFunction_)(int argNumber,
9499
torchArgErrorHandlerData = data;
95100
}
96101

102+
static __thread void (*torchGCFunction)(void *data) = NULL;
103+
static __thread void *torchGCData;
104+
static __thread long torchHeapSize = 0;
105+
static __thread long torchHeapSizeSoftMax = 300000000; // 300MB, adjusted upward dynamically
106+
107+
/* Optional hook for integrating with a garbage-collected frontend.
108+
*
109+
* If torch is running with a garbage-collected frontend (e.g. Lua),
110+
* the GC isn't aware of TH-allocated memory so may not know when it
111+
* needs to run. These hooks trigger the GC to run in two cases:
112+
*
113+
* (1) When a memory allocation (malloc, realloc, ...) fails
114+
* (2) When the total TH-allocated memory hits a dynamically-adjusted
115+
* soft maximum.
116+
*/
97117
void THSetGCHandler( void (*torchGCFunction_)(void *data), void *data )
98118
{
99119
torchGCFunction = torchGCFunction_;
100120
torchGCData = data;
101121
}
102122

103-
void* THAllocInternal(long size)
123+
static long getAllocSize(void *ptr) {
124+
#if defined(TH_DISABLE_HEAP_TRACKING)
125+
return 0;
126+
#elif defined(__unix)
127+
return malloc_usable_size(ptr);
128+
#elif defined(__APPLE__)
129+
return malloc_size(ptr);
130+
#elif defined(_WIN32)
131+
return _msize(ptr);
132+
#else
133+
return 0;
134+
#endif
135+
}
136+
137+
/* (1) if the torch-allocated heap size exceeds the soft max, run GC
138+
* (2) if post-GC heap size exceeds 80% of the soft max, increase the
139+
* soft max by 40%
140+
*/
141+
static void maybeTriggerGC() {
142+
if(torchGCFunction && torchHeapSize > torchHeapSizeSoftMax) {
143+
torchGCFunction(torchGCData);
144+
if(torchHeapSize > torchHeapSizeSoftMax * 0.8) {
145+
torchHeapSizeSoftMax = torchHeapSizeSoftMax * 1.4;
146+
}
147+
}
148+
}
149+
150+
// hooks into the TH heap tracking
151+
void THHeapUpdate(long size) {
152+
torchHeapSize += size;
153+
if (size > 0)
154+
maybeTriggerGC();
155+
}
156+
157+
static void* THAllocInternal(long size)
104158
{
105159
void *ptr;
106160

@@ -119,6 +173,8 @@ void* THAllocInternal(long size)
119173
{
120174
ptr = malloc(size);
121175
}
176+
177+
THHeapUpdate(getAllocSize(ptr));
122178
return ptr;
123179
}
124180

@@ -159,12 +215,14 @@ void* THRealloc(void *ptr, long size)
159215
if(size < 0)
160216
THError("$ Torch: invalid memory size -- maybe an overflow?");
161217

218+
THHeapUpdate(-getAllocSize(ptr));
162219
void *newptr = realloc(ptr, size);
163220

164221
if(!newptr && torchGCFunction) {
165222
torchGCFunction(torchGCData);
166223
newptr = realloc(ptr, size);
167224
}
225+
THHeapUpdate(getAllocSize(newptr ? newptr : ptr));
168226

169227
if(!newptr)
170228
THError("$ Torch: not enough memory: you tried to reallocate %dGB. Buy new RAM!", size/1073741824);
@@ -174,6 +232,7 @@ void* THRealloc(void *ptr, long size)
174232

175233
void THFree(void *ptr)
176234
{
235+
THHeapUpdate(-getAllocSize(ptr));
177236
free(ptr);
178237
}
179238

THGeneral.h.in

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,8 @@ TH_API void* THAlloc(long size);
5353
TH_API void* THRealloc(void *ptr, long size);
5454
TH_API void THFree(void *ptr);
5555
TH_API void THSetGCHandler( void (*torchGCHandlerFunction)(void *data), void *data );
56+
// this hook should only be called by custom allocator functions
57+
TH_API void THHeapUpdate(long size);
5658

5759
#define THError(...) _THError(__FILE__, __LINE__, __VA_ARGS__)
5860
#define THArgCheck(...) _THArgCheck(__FILE__, __LINE__, __VA_ARGS__)

0 commit comments

Comments
 (0)