Browse Source

memalloc: Compute evictability at initialization, so it is costless to determine it and can be used to avoid useless LRU management

Samuel Thibault 5 years ago
parent
commit
40b6341ca4
4 changed files with 63 additions and 37 deletions
  1. 3 0
      src/core/disk.c
  2. 2 0
      src/core/topology.c
  3. 54 36
      src/datawizard/memalloc.c
  4. 4 1
      src/datawizard/memalloc.h

+ 3 - 0
src/core/disk.c

@@ -148,6 +148,9 @@ int starpu_disk_register(struct starpu_disk_ops *func, void *parameter, starpu_s
 		return -ENOENT;
 		return -ENOENT;
 	if (size >= 0)
 	if (size >= 0)
 		_starpu_memory_manager_set_global_memory_size(disk_memnode, size);
 		_starpu_memory_manager_set_global_memory_size(disk_memnode, size);
+
+	_starpu_mem_chunk_disk_register(disk_memnode);
+
 	return disk_memnode;
 	return disk_memnode;
 }
 }
 
 

+ 2 - 0
src/core/topology.c

@@ -2853,6 +2853,8 @@ int _starpu_build_topology(struct _starpu_machine_config *config, int no_mp_conf
 
 
 	_starpu_init_workers_binding_and_memory(config, no_mp_config);
 	_starpu_init_workers_binding_and_memory(config, no_mp_config);
 
 
+	_starpu_mem_chunk_init_last();
+
 	config->cpus_nodeid = -1;
 	config->cpus_nodeid = -1;
 	config->cuda_nodeid = -1;
 	config->cuda_nodeid = -1;
 	config->opencl_nodeid = -1;
 	config->opencl_nodeid = -1;

+ 54 - 36
src/datawizard/memalloc.c

@@ -120,9 +120,59 @@ int _starpu_is_reclaiming(unsigned node)
 	return tidying[node] || reclaiming[node];
 	return tidying[node] || reclaiming[node];
 }
 }
 
 
+/* Whether this memory node can evict data to another node */
+static unsigned evictable[STARPU_MAXNODES];
+
+static int can_evict(unsigned node)
+{
+	return evictable[node];
+}
+
+/* Called after initializing the set of memory nodes */
+/* We use an accelerator -> CPU RAM -> disk storage hierarchy */
+void _starpu_mem_chunk_init_last(void)
+{
+	unsigned disk = 0;
+	unsigned nnodes = starpu_memory_nodes_get_count(), i;
+
+	for (i = 0; i < nnodes; i++)
+	{
+		enum starpu_node_kind kind = starpu_node_get_kind(i);
+
+		if (kind == STARPU_DISK_RAM)
+			/* Some disk, will be able to evict RAM */
+			/* TODO: disk hierarchy */
+			disk = 1;
+
+		else if (kind != STARPU_CPU_RAM)
+			/* This is an accelerator, we can evict to main RAM */
+			evictable[i] = 1;
+	}
+
+	if (disk)
+		for (i = 0; i < nnodes; i++)
+		{
+			enum starpu_node_kind kind = starpu_node_get_kind(i);
+			if (kind == STARPU_CPU_RAM)
+				evictable[i] = 1;
+		}
+}
+
+/* A disk was registered, RAM is now evictable */
+void _starpu_mem_chunk_disk_register(unsigned disk_memnode)
+{
+	unsigned nnodes = starpu_memory_nodes_get_count(), i;
+
+	for (i = 0; i < nnodes; i++)
+	{
+		enum starpu_node_kind kind = starpu_node_get_kind(i);
+		if (kind == STARPU_CPU_RAM)
+			evictable[i] = 1;
+	}
+}
+
 static int get_better_disk_can_accept_size(starpu_data_handle_t handle, unsigned node);
 static int get_better_disk_can_accept_size(starpu_data_handle_t handle, unsigned node);
 static int choose_target(starpu_data_handle_t handle, unsigned node);
 static int choose_target(starpu_data_handle_t handle, unsigned node);
-static int can_evict(unsigned node);
 
 
 void _starpu_init_mem_chunk_lists(void)
 void _starpu_init_mem_chunk_lists(void)
 {
 {
@@ -1575,10 +1625,9 @@ void _starpu_memchunk_recently_used(struct _starpu_mem_chunk *mc, unsigned node)
 	if (!mc)
 	if (!mc)
 		/* user-allocated memory */
 		/* user-allocated memory */
 		return;
 		return;
-	if (starpu_memory_nodes_get_count() == 1)
+	if (!can_evict(node))
 		/* Don't bother */
 		/* Don't bother */
 		return;
 		return;
-	/* TODO: return also on can_evict() == 0, after making can_evict costless */
 	_starpu_spin_lock(&mc_lock[node]);
 	_starpu_spin_lock(&mc_lock[node]);
 	MC_LIST_ERASE(node, mc);
 	MC_LIST_ERASE(node, mc);
 	mc->wontuse = 0;
 	mc->wontuse = 0;
@@ -1593,10 +1642,9 @@ void _starpu_memchunk_wont_use(struct _starpu_mem_chunk *mc, unsigned node)
 	if (!mc)
 	if (!mc)
 		/* user-allocated memory */
 		/* user-allocated memory */
 		return;
 		return;
-	if (starpu_memory_nodes_get_count() == 1)
+	if (!can_evict(node))
 		/* Don't bother */
 		/* Don't bother */
 		return;
 		return;
-	/* TODO: return also on can_evict() == 0, after making can_evict costless */
 	_starpu_spin_lock(&mc_lock[node]);
 	_starpu_spin_lock(&mc_lock[node]);
 	/* Avoid preventing it from being evicted */
 	/* Avoid preventing it from being evicted */
 	mc->diduse = 1;
 	mc->diduse = 1;
@@ -1621,10 +1669,9 @@ void _starpu_memchunk_dirty(struct _starpu_mem_chunk *mc, unsigned node)
 	if (mc->home)
 	if (mc->home)
 		/* Home is always clean */
 		/* Home is always clean */
 		return;
 		return;
-	if (starpu_memory_nodes_get_count() == 1)
+	if (!can_evict(node))
 		/* Don't bother */
 		/* Don't bother */
 		return;
 		return;
-	/* TODO: return also on can_evict() == 0, after making can_evict costless */
 	_starpu_spin_lock(&mc_lock[node]);
 	_starpu_spin_lock(&mc_lock[node]);
 	if (mc->relaxed_coherency == 1)
 	if (mc->relaxed_coherency == 1)
 	{
 	{
@@ -1798,35 +1845,6 @@ choose_target(starpu_data_handle_t handle, unsigned node)
 	return target;
 	return target;
 }
 }
 
 
-/* Whether this memory node can evict data to another node */
-/* We use an accelerator -> CPU RAM -> disk storage hierarchy */
-static int
-can_evict(unsigned node)
-{
-	enum starpu_node_kind kind = starpu_node_get_kind(node);
-
-	if (kind == STARPU_DISK_RAM)
-		/* TODO: disk hierarchy */
-		return 0;
-
-	if (kind != STARPU_CPU_RAM)
-		/* This is an accelerator, we can evict to main RAM */
-		return 1;
-
-	/* This is main RAM */
-	unsigned i;
-	unsigned nnodes = starpu_memory_nodes_get_count();
-	for (i = 0; i < nnodes; i++)
-	{
-		if (starpu_node_get_kind(i) == STARPU_DISK_RAM)
-			/* Can evict it to that disk */
-			return 1;
-	}
-
-	/* No disk to push main RAM to */
-	return 0;
-}
-
 void starpu_data_set_user_data(starpu_data_handle_t handle, void* user_data)
 void starpu_data_set_user_data(starpu_data_handle_t handle, void* user_data)
 {
 {
 	handle->user_data = user_data;
 	handle->user_data = user_data;

+ 4 - 1
src/datawizard/memalloc.h

@@ -1,6 +1,6 @@
 /* StarPU --- Runtime system for heterogeneous multicore architectures.
 /* StarPU --- Runtime system for heterogeneous multicore architectures.
  *
  *
- * Copyright (C) 2008-2015,2017,2018                      Université de Bordeaux
+ * Copyright (C) 2008-2015,2017,2018-2019                 Université de Bordeaux
  * Copyright (C) 2010-2013,2015,2017                      CNRS
  * Copyright (C) 2010-2013,2015,2017                      CNRS
  *
  *
  * StarPU is free software; you can redistribute it and/or modify
  * StarPU is free software; you can redistribute it and/or modify
@@ -81,6 +81,7 @@ LIST_TYPE(_starpu_mem_chunk,
 
 
 void _starpu_init_mem_chunk_lists(void);
 void _starpu_init_mem_chunk_lists(void);
 void _starpu_deinit_mem_chunk_lists(void);
 void _starpu_deinit_mem_chunk_lists(void);
+void _starpu_mem_chunk_init_last(void);
 void _starpu_request_mem_chunk_removal(starpu_data_handle_t handle, struct _starpu_data_replicate *replicate, unsigned node, size_t size);
 void _starpu_request_mem_chunk_removal(starpu_data_handle_t handle, struct _starpu_data_replicate *replicate, unsigned node, size_t size);
 int _starpu_allocate_memory_on_node(starpu_data_handle_t handle, struct _starpu_data_replicate *replicate, unsigned is_prefetch);
 int _starpu_allocate_memory_on_node(starpu_data_handle_t handle, struct _starpu_data_replicate *replicate, unsigned is_prefetch);
 size_t _starpu_free_all_automatically_allocated_buffers(unsigned node);
 size_t _starpu_free_all_automatically_allocated_buffers(unsigned node);
@@ -92,4 +93,6 @@ void _starpu_display_memory_stats_by_node(int node);
 size_t _starpu_memory_reclaim_generic(unsigned node, unsigned force, size_t reclaim);
 size_t _starpu_memory_reclaim_generic(unsigned node, unsigned force, size_t reclaim);
 int _starpu_is_reclaiming(unsigned node);
 int _starpu_is_reclaiming(unsigned node);
 
 
+void _starpu_mem_chunk_disk_register(unsigned disk_memnode);
+
 #endif
 #endif