int memkind_arena_destroy(struct memkind *kind) { char cmd[128]; int i; if (kind->arena_map) { for (i = 0; i < kind->arena_map_len; ++i) { snprintf(cmd, 128, "arena.%u.purge", kind->arena_map[i]); jemk_mallctl(cmd, NULL, NULL, NULL, 0); } jemk_free(kind->arena_map); kind->arena_map = NULL; #ifndef MEMKIND_TLS if (kind->ops->get_arena == memkind_thread_get_arena) { pthread_key_delete(kind->arena_key); } #endif } memkind_default_destroy(kind); return 0; }
int memkind_arena_create_map(struct memkind *kind) { int err = 0; int i; size_t unsigned_size = sizeof(unsigned int); if (kind->arena_map_len == 0) { err = memkind_set_arena_map_len(kind); } #ifndef MEMKIND_TLS if (kind->ops->get_arena == memkind_thread_get_arena) { pthread_key_create(&(kind->arena_key), jemk_free); } #endif if (kind->arena_map_len) { kind->arena_map = (unsigned int *)jemk_malloc(sizeof(unsigned int) * kind->arena_map_len); if (kind->arena_map == NULL) { err = MEMKIND_ERROR_MALLOC; } } if (!err) { for (i = 0; i < kind->arena_map_len; ++i) { kind->arena_map[i] = UINT_MAX; } for (i = 0; !err && i < kind->arena_map_len; ++i) { err = jemk_mallctl("arenas.extendk", kind->arena_map + i, &unsigned_size, &(kind->partition), unsigned_size); } if (err) { if (kind->arena_map) { jemk_free(kind->arena_map); } err = MEMKIND_ERROR_MALLCTL; } } return err; }
/** * Initialises the local heap space, the master will determine the local heap start address for each process. This is broadcast to all * processes who will then set up their own space via memkind, pin it & allocate the RMA window. All heaps are added into the directory * here. Note that there might be slight gaps between local heaps and the start of the global address space and the first heap, this is * because jemalloc requires the start address to divide into its chunk size so we have to round up to this. */ void *gvi_localHeap_initialise(int myRank, int totalRanks, void *global_base_address) { int i; struct memkind_ops *my_memkind_ops = (struct memkind_ops *)memkind_malloc(MEMKIND_DEFAULT, sizeof(struct memkind_ops)); memcpy(my_memkind_ops, &MEMKIND_PMEM_OPS, sizeof(struct memkind_ops)); my_memkind_ops->mmap = my_pmem_mmap; struct distmem_ops *localheap_vtable = (struct distmem_ops *)memkind_malloc(MEMKIND_DEFAULT, sizeof(struct distmem_ops)); localheap_vtable->dist_malloc = NULL; localheap_vtable->dist_create = distmem_arena_create; localheap_vtable->memkind_operations = my_memkind_ops; localheap_vtable->dist_determine_distribution = NULL; distmem_create(localheap_vtable, "localheap", &LOCALHEAP_KIND); struct memkind_ops *my_memkind_ops_cache = (struct memkind_ops *)memkind_malloc(MEMKIND_DEFAULT, sizeof(struct memkind_ops)); memcpy(my_memkind_ops_cache, &MEMKIND_PMEM_OPS, sizeof(struct memkind_ops)); my_memkind_ops_cache->mmap = my_pmem_mmap; struct distmem_ops *localheap_vtable_cache = (struct distmem_ops *)memkind_malloc(MEMKIND_DEFAULT, sizeof(struct distmem_ops)); localheap_vtable_cache->dist_malloc = NULL; localheap_vtable_cache->dist_create = distmem_arena_create; localheap_vtable_cache->memkind_operations = my_memkind_ops_cache; localheap_vtable_cache->dist_determine_distribution = NULL; distmem_create(localheap_vtable_cache, "localheap_cache", &INTERNAL_LOCALCACHE_KIND); size_t jemk_chunksize_exponent; size_t s = sizeof(jemk_chunksize_exponent); jemk_mallctl("opt.lg_chunk", &jemk_chunksize_exponent, &s, NULL, 0); int jemk_chunksize = (int)pow(2.0, jemk_chunksize_exponent); unsigned long start_addresses[totalRanks]; if (myRank == MASTER_RANK) { for (i = 0; i < totalRanks; i++) { if (i == 0) { start_addresses[i] = (unsigned long)global_base_address; } else { start_addresses[i] = start_addresses[i - 1] + LOCAL_HEAP_SIZE; } start_addresses[i] = roundup(start_addresses[i], jemk_chunksize); } } MPI_Bcast(start_addresses, totalRanks, MPI_UNSIGNED_LONG, MASTER_RANK, MPI_COMM_WORLD); unsigned long local_cache_start_address = roundup(start_addresses[myRank] + (LOCAL_HEAP_SIZE - LOCAL_CACHE_SIZE), jemk_chunksize); struct memkind_pmem *priv = (struct memkind_pmem *)INTERNAL_LOCALCACHE_KIND->priv; priv->fd = 0; priv->addr = (void *)local_cache_start_address; priv->max_size = LOCAL_HEAP_SIZE - (local_cache_start_address - 1 - start_addresses[myRank]); priv->offset = 0; priv = (struct memkind_pmem *)LOCALHEAP_KIND->priv; priv->fd = 0; priv->addr = (void *)start_addresses[myRank]; priv->max_size = local_cache_start_address - 1 - start_addresses[myRank]; priv->offset = 0; mlock(priv->addr, LOCAL_HEAP_SIZE); for (i = 0; i < totalRanks; i++) { gvi_directory_registerMemory((void *)start_addresses[i], LOCAL_HEAP_SIZE, i); } MPI_Win win; MPI_Win_create(priv->addr, LOCAL_HEAP_SIZE, 1, MPI_INFO_NULL, MPI_COMM_WORLD, &win); gvi_cache_registerLocalHeap(win, global_base_address, start_addresses, totalRanks); return priv->addr; }