The realloc included with openmpi 1.2.3 is not releasing memory to the
OS and is causing apps to go into swap.  Attached is a little test
program that shows calls to realloc not releasing the memory when
compiled using mpicc, but when compiled directly with gcc (or icc)
calling realloc() frees any memory no longer needed.

Is this a bug?

If not, how can I force openmpi to free the memory that the allocator
is sitting on?

Thanks,
Josh

Sample output.  Note the delta between 'total' and 'malloc held' when
compiled with mpicc and how the gcc compiled versions track perfectly.

$ mpicc -o realloc_test realloc_test.c
$ ./realloc_test
...
malloc/realloc/free test
malloc()    50 MB, total   50 MB, malloc held   50 MB
realloc()    1 MB, total    1 MB, malloc held   50 MB
malloc()    50 MB, total   51 MB, malloc held  100 MB
realloc()    1 MB, total    2 MB, malloc held  100 MB
malloc()    50 MB, total   52 MB, malloc held  150 MB
realloc()    1 MB, total    3 MB, malloc held  150 MB
malloc()    50 MB, total   53 MB, malloc held  200 MB
realloc()    1 MB, total    4 MB, malloc held  200 MB
malloc()    50 MB, total   54 MB, malloc held  250 MB
realloc()    1 MB, total    5 MB, malloc held  250 MB
free()       1 MB, total    4 MB, malloc held  200 MB
free()       1 MB, total    3 MB, malloc held  150 MB
free()       1 MB, total    2 MB, malloc held  100 MB
free()       1 MB, total    1 MB, malloc held   50 MB
free()       1 MB, total    0 MB, malloc held    0 MB
...

$ gcc -o realloc_test realloc_test.c
$ ./realloc_test
...
malloc/realloc/free test
malloc()    50 MB, total   50 MB, malloc held   50 MB
realloc()    1 MB, total    1 MB, malloc held    1 MB
malloc()    50 MB, total   51 MB, malloc held   51 MB
realloc()    1 MB, total    2 MB, malloc held    2 MB
malloc()    50 MB, total   52 MB, malloc held   52 MB
realloc()    1 MB, total    3 MB, malloc held    3 MB
malloc()    50 MB, total   53 MB, malloc held   53 MB
realloc()    1 MB, total    4 MB, malloc held    4 MB
malloc()    50 MB, total   54 MB, malloc held   54 MB
realloc()    1 MB, total    5 MB, malloc held    5 MB
free()       1 MB, total    4 MB, malloc held    4 MB
free()       1 MB, total    3 MB, malloc held    3 MB
free()       1 MB, total    2 MB, malloc held    2 MB
free()       1 MB, total    1 MB, malloc held    1 MB
free()       1 MB, total    0 MB, malloc held    0 MB
...
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <malloc.h>
#include <sys/mman.h>

#define MegB (1024*1024)

#define CHUNKSIZE 50*MegB       // initial buffer size to malloc
#define CHUNKREALLOC 1*MegB     // Reallocate the buffer to this size
#define CHUNKDECREASEBY 2*MegB  // decrease malloced buffer by this

#define COUNT 5			// Number of iterations to do

/* Touch one byte on every page of allocated memory to ensure it
   gets requested from the kernel */
void touch_memory(char *base, int size)
{
	int pagesize;
	int offset;
	int i;

	pagesize = getpagesize();
	for(offset = 0; offset < size; offset += pagesize)
		base[offset] = 0xff;
}

int get_malloc_held(void)
{
	struct mallinfo info = mallinfo();
	return info.hblkhd/MegB;
}

void print_mem_usage(void)
{
	struct mallinfo info = mallinfo();
	
	printf("  Current usage is:\n");
	printf("    arena: %d\n", info.arena);
	printf("    ordblks: %d\n", info.ordblks);
	printf("    smblks: %d\n", info.smblks);
	printf("    Number of buckets: %d\n", info.hblks);
	printf("    Size of all buckets: %d MB\n", info.hblkhd/MegB);
	printf("    usmblks: %d\n", info.usmblks);
	printf("    fsmblks: %d\n", info.fsmblks);
	printf("    uordblks: %d\n", info.uordblks);
	printf("    fordblks: %d\n", info.fordblks);
	printf("    keepcost: %d\n", info.keepcost);
}

int main(int argc, char **argv)
{
	void *ptrs[COUNT];
	int i;
	int alloc_size;
	int total_mb;
	
	printf("malloc/free test\n");
	alloc_size = CHUNKSIZE;
	total_mb = 0;
	for(i = 0; i < COUNT; i++) {
		ptrs[i] = malloc(alloc_size);
		touch_memory(ptrs[i], alloc_size);
		total_mb += alloc_size/MegB;
		printf("malloc() % 5d MB, total % 4d MB, malloc held % 4d MB\n", 
			alloc_size/MegB, total_mb, get_malloc_held());
	}
	for(i = 0; i < COUNT; i++) {
		free(ptrs[COUNT-1-i]);
		total_mb -= alloc_size/MegB;
		printf("free() % 7d MB, total % 4d MB, malloc held % 4d MB\n", 
			alloc_size/MegB, total_mb, get_malloc_held());
	}

	
	printf("\nmalloc/realloc/free test\n");
	alloc_size = CHUNKSIZE;
	total_mb = 0;
	for(i = 0; i < COUNT; i++) {
		ptrs[i] = malloc(alloc_size);
		madvise(ptrs[i], alloc_size, MADV_NORMAL);
		touch_memory(ptrs[i], alloc_size);
		total_mb += alloc_size/MegB;
		printf("malloc() % 5d MB, total % 4d MB, malloc held % 4d MB\n", 
			alloc_size/MegB, total_mb, get_malloc_held());
		
		ptrs[i] = realloc(ptrs[i], CHUNKREALLOC);
		madvise(ptrs[i], CHUNKREALLOC, MADV_NORMAL);
		total_mb = total_mb-alloc_size/MegB+CHUNKREALLOC/MegB;
		printf("realloc() % 4d MB, total % 4d MB, malloc held % 4d MB\n", 
 			CHUNKREALLOC/MegB, total_mb, get_malloc_held());
	}
	for(i = 0; i < COUNT; i++) {
		free(ptrs[COUNT-1-i]);
		total_mb -= CHUNKREALLOC/MegB;
		printf("free() % 7d MB, total % 4d MB, malloc held % 4d MB\n", 
			CHUNKREALLOC/MegB, total_mb, get_malloc_held());
	}

	printf("\nmalloc/realloc/free with decrementing size test\n");
	alloc_size = CHUNKSIZE;
	total_mb = 0;
	for(i = 0; i < COUNT; i++) {
		ptrs[i] = malloc(alloc_size);
		madvise(ptrs[i], alloc_size, MADV_NORMAL);
		touch_memory(ptrs[i], alloc_size);
		total_mb += alloc_size/MegB;
		printf("malloc() % 5d MB, total % 4d MB, malloc held % 4d MB\n", 
			alloc_size/MegB, total_mb, get_malloc_held());

		ptrs[i] = realloc(ptrs[i], CHUNKREALLOC);
		madvise(ptrs[i], CHUNKREALLOC, MADV_NORMAL);
		total_mb = total_mb-alloc_size/MegB+CHUNKREALLOC/MegB;
		printf("realloc() % 4d MB, total % 4d MB, malloc held % 4d MB\n", 
 			CHUNKREALLOC/MegB, total_mb, get_malloc_held());

		alloc_size -= CHUNKDECREASEBY;
	}
	for(i = 0; i < COUNT; i++) {
		free(ptrs[COUNT-1-i]);
		total_mb -= CHUNKREALLOC/MegB;
		printf("free() % 7d MB, total % 4d MB, malloc held % 4d MB\n", 
			CHUNKREALLOC/MegB, total_mb, get_malloc_held());
	}


}

Reply via email to