From c2798a8bd6dddf68b69608ee04500261a0eda842 Mon Sep 17 00:00:00 2001 From: Igor Ivanov Date: Wed, 10 Feb 2016 14:27:47 +0200 Subject: [PATCH 1/2] opal/memory: Move Memory Allocation Hooks usage from openib These changes fix issue https://github.com/open-mpi/ompi/issues/1336 - improve abstractions: opal/memory/linux component should be single place that opeartes with Memory Allocation Hooks. - avoid collisions in case dynamic component open/close: it is safe because it is linked statically. - does not change original behaivour. --- ompi/mca/btl/openib/btl_openib.h | 5 - ompi/mca/btl/openib/btl_openib_component.c | 77 +--------- ompi/mca/btl/openib/btl_openib_mca.c | 43 ++---- ompi/mca/btl/openib/configure.m4 | 23 --- ompi/runtime/ompi_mpi_init.c | 2 +- opal/mca/memory/base/empty.h | 13 +- opal/mca/memory/base/memory_base_empty.c | 8 + opal/mca/memory/base/memory_base_open.c | 3 + opal/mca/memory/linux/configure.m4 | 36 +++++ .../memory/linux/help-opal-memory-linux.txt | 7 + opal/mca/memory/linux/hooks.c | 6 +- opal/mca/memory/linux/memory_linux.h | 14 +- .../mca/memory/linux/memory_linux_component.c | 145 +++++++++++++++++- .../memory_malloc_solaris_component.c | 10 +- opal/mca/memory/memory.h | 19 ++- 15 files changed, 266 insertions(+), 145 deletions(-) diff --git a/ompi/mca/btl/openib/btl_openib.h b/ompi/mca/btl/openib/btl_openib.h index 032d1035cb..fadfc04862 100644 --- a/ompi/mca/btl/openib/btl_openib.h +++ b/ompi/mca/btl/openib/btl_openib.h @@ -310,11 +310,6 @@ struct mca_btl_openib_component_t { #if BTL_OPENIB_FAILOVER_ENABLED int verbose_failover; #endif -#if BTL_OPENIB_MALLOC_HOOKS_ENABLED - int use_memalign; - size_t memalign_threshold; - void* (*previous_malloc_hook)(size_t __size, const void*); -#endif #if OPAL_CUDA_SUPPORT bool cuda_async_send; bool cuda_async_recv; diff --git a/ompi/mca/btl/openib/btl_openib_component.c b/ompi/mca/btl/openib/btl_openib_component.c index ae68a540e4..4ab7a6beeb 100644 --- a/ompi/mca/btl/openib/btl_openib_component.c +++ b/ompi/mca/btl/openib/btl_openib_component.c @@ -11,7 +11,7 @@ * Copyright (c) 2004-2005 The Regents of the University of California. * All rights reserved. * Copyright (c) 2006-2013 Cisco Systems, Inc. All rights reserved. - * Copyright (c) 2006-2009 Mellanox Technologies. All rights reserved. + * Copyright (c) 2006-2016 Mellanox Technologies. All rights reserved. * Copyright (c) 2006-2013 Los Alamos National Security, LLC. All rights * reserved. * Copyright (c) 2006-2007 Voltaire All rights reserved. @@ -19,7 +19,7 @@ * Copyright (c) 2011-2014 NVIDIA Corporation. All rights reserved. * Copyright (c) 2012 Oak Ridge National Laboratory. All rights reserved * Copyright (c) 2013 Intel, Inc. All rights reserved - * Copyright (c) 2014-2015 Research Organization for Information Science + * Copyright (c) 2014-2016 Research Organization for Information Science * and Technology (RIST). All rights reserved. * Copyright (c) 2014 Bull SAS. All rights reserved. * $COPYRIGHT$ @@ -42,22 +42,8 @@ #include #include #include -#if BTL_OPENIB_MALLOC_HOOKS_ENABLED -/* - * The include of malloc.h below breaks abstractions in OMPI (by - * directly including a header file from another component), but has - * been ruled "ok" because the openib component is only supported on - * Linux. - * - * The malloc hooks in newer glibc were deprecated, including stock - * malloc.h causes compilation warnings. Instead, we use the internal - * linux component malloc.h which does not cause these warnings. - * Internally, OMPI uses the built-in ptmalloc from the linux memory - * component anyway. - */ -#include "opal/mca/memory/linux/malloc.h" -#endif +#include "opal/mca/memory/memory.h" #include "opal/mca/event/event.h" #include "opal/align.h" #include "opal/util/output.h" @@ -129,7 +115,6 @@ static void btl_openib_handle_incoming_completion(mca_btl_base_module_t* btl, * Local variables */ static mca_btl_openib_device_t *receive_queues_device = NULL; -static bool malloc_hook_set = false; static int num_devices_intentionally_ignored = 0; mca_btl_openib_component_t mca_btl_openib_component = { @@ -159,30 +144,6 @@ mca_btl_openib_component_t mca_btl_openib_component = { } }; -#if BTL_OPENIB_MALLOC_HOOKS_ENABLED -/* This is a memory allocator hook. The purpose of this is to make - * every malloc aligned since this speeds up IB HCA work. - * There two basic cases here: - * - * 1. Memory manager for Open MPI is enabled. Then memalign below will - * be overridden by __memalign_hook which is set to - * opal_memory_linux_memalign_hook. Thus, _malloc_hook is going to - * use opal_memory_linux_memalign_hook. - * - * 2. No memory manager support. The memalign below is just regular glibc - * memalign which will be called through __malloc_hook instead of malloc. - */ -static void *btl_openib_malloc_hook(size_t sz, const void* caller) -{ - if (sz < mca_btl_openib_component.memalign_threshold && - malloc_hook_set) { - return mca_btl_openib_component.previous_malloc_hook(sz, caller); - } else { - return memalign(mca_btl_openib_component.use_memalign, sz); - } -} -#endif - static int btl_openib_component_register(void) { int ret; @@ -287,16 +248,6 @@ static int btl_openib_component_close(void) if (NULL != mca_btl_openib_component.default_recv_qps) { free(mca_btl_openib_component.default_recv_qps); } - -#if BTL_OPENIB_MALLOC_HOOKS_ENABLED - /* Must check to see whether the malloc hook was set before - assigning it back because ompi_info will call _register() and - then _close() (which won't set the hook) */ - if (malloc_hook_set) { - __malloc_hook = mca_btl_openib_component.previous_malloc_hook; - malloc_hook_set = false; - } -#endif /* close memory registration debugging output */ opal_output_close (mca_btl_openib_component.memory_registration_verbose); @@ -2461,19 +2412,8 @@ btl_openib_component_init(int *num_btl_modules, *num_btl_modules = 0; num_devs = 0; -#if BTL_OPENIB_MALLOC_HOOKS_ENABLED - /* If we got this far, then setup the memory alloc hook (because - we're most likely going to be using this component). The hook - is to be set up as early as possible in this function since we - want most of the allocated resources be aligned.*/ - if (mca_btl_openib_component.use_memalign > 0 && - (opal_mem_hooks_support_level() & - (OPAL_MEMORY_FREE_SUPPORT | OPAL_MEMORY_CHUNK_SUPPORT)) != 0) { - mca_btl_openib_component.previous_malloc_hook = __malloc_hook; - __malloc_hook = btl_openib_malloc_hook; - malloc_hook_set = true; - } -#endif + opal_memory->memoryc_set_alignment(32, mca_btl_openib_module.super.btl_eager_limit); + /* Currently refuse to run if MPI_THREAD_MULTIPLE is enabled */ if (ompi_mpi_thread_multiple && !mca_btl_base_thread_multiple_override) { opal_output_verbose(5, ompi_btl_base_framework.framework_output, @@ -2894,13 +2834,6 @@ btl_openib_component_init(int *num_btl_modules, mca_btl_openib_component.ib_num_btls = 0; btl_openib_modex_send(); -#if BTL_OPENIB_MALLOC_HOOKS_ENABLED - /*Unset malloc hook since the component won't start*/ - if (malloc_hook_set) { - __malloc_hook = mca_btl_openib_component.previous_malloc_hook; - malloc_hook_set = false; - } -#endif return NULL; } diff --git a/ompi/mca/btl/openib/btl_openib_mca.c b/ompi/mca/btl/openib/btl_openib_mca.c index 769e9fc461..73fa235037 100644 --- a/ompi/mca/btl/openib/btl_openib_mca.c +++ b/ompi/mca/btl/openib/btl_openib_mca.c @@ -703,26 +703,18 @@ int btl_openib_register_mca_params(void) 0, &mca_btl_openib_component.gid_index, REGINT_GE_ZERO)); -#if BTL_OPENIB_MALLOC_HOOKS_ENABLED - CHECK(reg_int("memalign", NULL, - "[64 | 32 | 0] - Enable (64bit or 32bit)/Disable(0) memory" - "alignment for all malloc calls if btl openib is used.", - 32, &mca_btl_openib_component.use_memalign, - REGINT_GE_ZERO)); - - mca_btl_openib_component.memalign_threshold = - mca_btl_openib_module.super.btl_eager_limit; - tmp = mca_base_component_var_register(&mca_btl_openib_component.super.btl_version, - "memalign_threshold", - "Allocating memory more than btl_openib_memalign_threshhold" - "bytes will automatically be aligned to the value of btl_openib_memalign bytes." - "memalign_threshhold defaults to the same value as mca_btl_openib_eager_limit.", - MCA_BASE_VAR_TYPE_SIZE_T, NULL, 0, 0, - OPAL_INFO_LVL_9, - MCA_BASE_VAR_SCOPE_READONLY, - &mca_btl_openib_component.memalign_threshold); - if (0 > tmp) ret = tmp; -#endif +#if MEMORY_LINUX_MALLOC_ALIGN_ENABLED + tmp = mca_base_var_find ("opal", "memory", "linux", "memalign"); + if (0 <= tmp) { + (void) mca_base_var_register_synonym(tmp, "ompi", "btl", "openib", "memalign", + MCA_BASE_VAR_SYN_FLAG_DEPRECATED); + } + tmp = mca_base_var_find ("opal", "memory", "linux", "memalign_threshold"); + if (0 <= tmp) { + (void) mca_base_var_register_synonym(tmp, "opal", "btl", "openib", "memalign_threshold", + MCA_BASE_VAR_SYN_FLAG_DEPRECATED); + } +#endif /* MEMORY_LINUX_MALLOC_ALIGN_ENABLED */ /* Register any MCA params for the connect pseudo-components */ if (OMPI_SUCCESS == ret) { @@ -816,16 +808,5 @@ int btl_openib_verify_mca_params (void) } #endif -#if BTL_OPENIB_MALLOC_HOOKS_ENABLED - if (mca_btl_openib_component.use_memalign != 32 - && mca_btl_openib_component.use_memalign != 64 - && mca_btl_openib_component.use_memalign != 0){ - opal_show_help("help-mpi-btl-openib.txt", "invalid mca param value", - true, "Wrong btl_openib_memalign parameter value. Allowed values: 64, 32, 0.", - "btl_openib_memalign is reset to 32"); - mca_btl_openib_component.use_memalign = 32; - } -#endif - return OMPI_SUCCESS; } diff --git a/ompi/mca/btl/openib/configure.m4 b/ompi/mca/btl/openib/configure.m4 index e247c6e086..070324ac28 100644 --- a/ompi/mca/btl/openib/configure.m4 +++ b/ompi/mca/btl/openib/configure.m4 @@ -129,29 +129,6 @@ AC_DEFUN([MCA_ompi_btl_openib_CONFIG],[ [enable openib BTL failover]) AM_CONDITIONAL([MCA_btl_openib_enable_failover], [test "x$btl_openib_failover_enabled" = "x1"]) - - # Check for __malloc_hook availability - AC_ARG_ENABLE(btl-openib-malloc-alignment, - AC_HELP_STRING([--enable-btl-openib-malloc-alignment], [Enable support for allocated memory alignment. Default: enabled if supported, disabled otherwise.])) - - btl_openib_malloc_hooks_enabled=0 - AS_IF([test "$enable_btl_openib_malloc_alignment" != "no"], - [AC_CHECK_HEADER([malloc.h], - [AC_CHECK_FUNC([__malloc_hook], - [AC_CHECK_FUNC([__realloc_hook], - [AC_CHECK_FUNC([__free_hook], - [btl_openib_malloc_hooks_enabled=1])])])])]) - - AS_IF([test "$enable_btl_openib_malloc_alignment" = "yes" -a "$btl_openib_malloc_hooks_enabled" = "0"], - [AC_MSG_ERROR([openib malloc alignment is requested but __malloc_hook is not available])]) - AC_MSG_CHECKING([whether the openib BTL will use malloc hooks]) - AS_IF([test "$btl_openib_malloc_hooks_enabled" = "0"], - [AC_MSG_RESULT([no])], - [AC_MSG_RESULT([yes])]) - - AC_DEFINE_UNQUOTED(BTL_OPENIB_MALLOC_HOOKS_ENABLED, [$btl_openib_malloc_hooks_enabled], - [Whether the openib BTL malloc hooks are enabled]) - # make sure that CUDA-aware checks have been done AC_REQUIRE([OPAL_CHECK_CUDA]) diff --git a/ompi/runtime/ompi_mpi_init.c b/ompi/runtime/ompi_mpi_init.c index 71864da166..67e08da8f6 100644 --- a/ompi/runtime/ompi_mpi_init.c +++ b/ompi/runtime/ompi_mpi_init.c @@ -103,7 +103,7 @@ from here, since any MPI code is going to call MPI_Init... */ OPAL_DECLSPEC void (*__malloc_initialize_hook) (void) = opal_memory_linux_malloc_init_hook; -#endif +#endif /* defined(MEMORY_LINUX_PTMALLOC2) && MEMORY_LINUX_PTMALLOC2 */ /* This is required for the boundaries of the hash tables used to store * the F90 types returned by the MPI_Type_create_f90_XXX functions. diff --git a/opal/mca/memory/base/empty.h b/opal/mca/memory/base/empty.h index 5067bf2f07..aa2d44d018 100644 --- a/opal/mca/memory/base/empty.h +++ b/opal/mca/memory/base/empty.h @@ -1,5 +1,7 @@ /* - * Copyright (c) 2009 Cisco Systems, Inc. All rights reserved. + * Copyright (c) 2009 Cisco Systems, Inc. All rights reserved. + * Copyright (c) 2016 Research Organization for Information Science + * and Technology (RIST). All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -51,6 +53,15 @@ OPAL_DECLSPEC int opal_memory_base_component_deregister_empty(void *start, size_t len, uint64_t cookie); +/** + * Default (empty) implementation of the memoryc_set_alignment function + * + * See opal/mca/memory/memory.h for a description of the parameters. + */ +OPAL_DECLSPEC void opal_memory_base_component_set_alignment_empty(int use_memalign, + size_t memalign_threshold); + + END_C_DECLS #endif diff --git a/opal/mca/memory/base/memory_base_empty.c b/opal/mca/memory/base/memory_base_empty.c index 804116a47b..296133d5df 100644 --- a/opal/mca/memory/base/memory_base_empty.c +++ b/opal/mca/memory/base/memory_base_empty.c @@ -9,6 +9,8 @@ * University of Stuttgart. All rights reserved. * Copyright (c) 2004-2005 The Regents of the University of California. * All rights reserved. + * Copyright (c) 2016 Research Organization for Information Science + * and Technology (RIST). All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -34,3 +36,9 @@ int opal_memory_base_component_deregister_empty(void *base, size_t len, { return OPAL_SUCCESS; } + +void opal_memory_base_component_set_alignment_empty(int use_memalign, + size_t memalign_threshold) +{ +} + diff --git a/opal/mca/memory/base/memory_base_open.c b/opal/mca/memory/base/memory_base_open.c index 75d3b8379f..e3f6988ba9 100644 --- a/opal/mca/memory/base/memory_base_open.c +++ b/opal/mca/memory/base/memory_base_open.c @@ -11,6 +11,8 @@ * Copyright (c) 2004-2005 The Regents of the University of California. * All rights reserved. * Copyright (c) 2009 Cisco Systems, Inc. All rights reserved. + * Copyright (c) 2016 Research Organization for Information Science + * and Technology (RIST). All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -54,6 +56,7 @@ static opal_memory_base_component_2_0_0_t empty_component = { empty_process, opal_memory_base_component_register_empty, opal_memory_base_component_deregister_empty, + opal_memory_base_component_set_alignment_empty, }; diff --git a/opal/mca/memory/linux/configure.m4 b/opal/mca/memory/linux/configure.m4 index 57e943c5a2..86f475736a 100644 --- a/opal/mca/memory/linux/configure.m4 +++ b/opal/mca/memory/linux/configure.m4 @@ -61,6 +61,42 @@ AC_DEFUN([MCA_opal_memory_linux_CONFIG],[ [memory_linux_ptmalloc2_happy=no memory_linux_ummu_happy=no])]) + + ###################################################################### + # if memory hook available + ###################################################################### + memory_hook_found=1 + AS_IF([test "$memory_hook_found" -eq 1], + [memory_hook_found=0 AC_CHECK_HEADER([malloc.h], + [AC_CHECK_FUNC([__malloc_initialize_hook], + [AC_CHECK_FUNC([__malloc_hook], + [AC_CHECK_FUNC([__realloc_hook], + [AC_CHECK_FUNC([__free_hook], + [memory_hook_found=1])])])])])]) + AC_MSG_CHECKING([whether the system can use malloc hooks]) + AS_IF([test "$memory_hook_found" = "0"], + [AC_MSG_RESULT([no])], + [AC_MSG_RESULT([yes])]) + AC_DEFINE_UNQUOTED([MEMORY_LINUX_HAVE_MALLOC_HOOK_SUPPORT], [$memory_hook_found], + [Whether the system has Memory Allocation Hooks]) + + AC_ARG_ENABLE(memory-linux-malloc-alignment, + AC_HELP_STRING([--enable-memory-linux-malloc-alignment], [Enable support for allocated memory alignment. Default: enabled if supported, disabled otherwise.])) + + malloc_align_enabled=0 + AS_IF([test "$enable_memory_linux_malloc_alignment" != "no"], + [malloc_align_enabled=$memory_hook_found]) + + AS_IF([test "$enable_memory_linux_malloc_alignment" = "yes" && test "$malloc_align_enabled" = "0"], + [AC_MSG_ERROR([memory linux malloc alignment is requested but __malloc_hook is not available])]) + AC_MSG_CHECKING([whether the memory linux will use malloc alignment]) + AS_IF([test "$malloc_align_enabled" = "0"], + [AC_MSG_RESULT([no])], + [AC_MSG_RESULT([yes])]) + + AC_DEFINE_UNQUOTED(MEMORY_LINUX_MALLOC_ALIGN_ENABLED, [$malloc_align_enabled], + [Whether the memory linux malloc alignment is enabled]) + ###################################################################### # ptmalloc2 ###################################################################### diff --git a/opal/mca/memory/linux/help-opal-memory-linux.txt b/opal/mca/memory/linux/help-opal-memory-linux.txt index 0f9db1f4c8..9db3123278 100644 --- a/opal/mca/memory/linux/help-opal-memory-linux.txt +++ b/opal/mca/memory/linux/help-opal-memory-linux.txt @@ -40,3 +40,10 @@ alternate memory hook manager *may* be used instead (if available). Local host: %s UMMU device: %s Error: %s (%d) +# +[invalid mca param value] +WARNING: An invalid MCA parameter value was found for memory/linux +component. + + Problem: %s + Resolution: %s diff --git a/opal/mca/memory/linux/hooks.c b/opal/mca/memory/linux/hooks.c index 0bfa123d6d..649478274b 100644 --- a/opal/mca/memory/linux/hooks.c +++ b/opal/mca/memory/linux/hooks.c @@ -34,6 +34,7 @@ #include "opal/mca/memory/memory.h" #include "opal/util/show_help.h" #include "opal/constants.h" +#include "opal/memoryhooks/memory.h" #include "opal/mca/memory/linux/memory_linux.h" @@ -735,7 +736,10 @@ static check_result_t check(const char *name) } } -/* OMPI's init function */ + +/* This function is called on loading libmpi in case system has Memory Allocation Hooks + * (see ompi/runtime/ompi_mpi_init.c for details) + */ void opal_memory_linux_malloc_init_hook(void) { check_result_t r1, lp, lpp; diff --git a/opal/mca/memory/linux/memory_linux.h b/opal/mca/memory/linux/memory_linux.h index 63a9ee95d2..eb9e628713 100644 --- a/opal/mca/memory/linux/memory_linux.h +++ b/opal/mca/memory/linux/memory_linux.h @@ -31,6 +31,11 @@ typedef struct opal_memory_linux_component_t { int ummunotify_fd; #endif +#if MEMORY_LINUX_MALLOC_ALIGN_ENABLED + int use_memalign; + size_t memalign_threshold; +#endif + #if MEMORY_LINUX_PTMALLOC2 /* Ptmalloc2-specific data. Note that these variables are all marked as volatile. * This is needed because of what may be a buggy optimization in the GCC 4.9.2 @@ -64,13 +69,20 @@ int opal_memory_linux_ummunotify_close(void); /* memory_linux_ptmalloc2.c */ int opal_memory_linux_ptmalloc2_open(void); int opal_memory_linux_ptmalloc2_close(void); -OPAL_DECLSPEC void opal_memory_linux_malloc_init_hook(void); /* memory_linux_munmap.c */ OPAL_DECLSPEC int opal_memory_linux_free_ptmalloc2_munmap(void *start, size_t length, int from_alloc); OPAL_DECLSPEC int munmap(void* addr, size_t len); #endif /* !MEMORY_LINUX_PTMALLOC2 */ +#if MEMORY_LINUX_HAVE_MALLOC_HOOK_SUPPORT +OPAL_DECLSPEC void opal_memory_linux_malloc_init_hook(void); +#endif /* MEMORY_LINUX_HAVE_MALLOC_HOOK_SUPPORT */ + +#if MEMORY_LINUX_MALLOC_ALIGN_ENABLED +OPAL_DECLSPEC void opal_memory_linux_malloc_set_alignment(int use_memalign, size_t memalign_threshold); +#endif /* MEMORY_LINUX_MALLOC_ALIGN_ENABLED */ + END_C_DECLS #endif diff --git a/opal/mca/memory/linux/memory_linux_component.c b/opal/mca/memory/linux/memory_linux_component.c index 4f0af66dda..fec41c7b33 100644 --- a/opal/mca/memory/linux/memory_linux_component.c +++ b/opal/mca/memory/linux/memory_linux_component.c @@ -13,10 +13,15 @@ * Copyright (c) 2009-2014 Cisco Systems, Inc. All rights reserved. * Copyright (c) 2013 Los Alamos National Security, LLC. * All rights reserved. + * Copyright (c) 2016 Research Organization for Information Science + * and Technology (RIST). All rights reserved. + * Copyright (c) 2016 Mellanox Technologies, Inc. + * All rights reserved. + * * $COPYRIGHT$ - * + * * Additional copyrights may follow - * + * * $HEADER$ */ @@ -39,12 +44,17 @@ #include "opal_config.h" +#if HAVE_MALLOC_H +#include +#endif + #include "opal/constants.h" #include "opal/mca/base/mca_base_var.h" #include "opal/mca/memory/memory.h" #include "opal/mca/memory/base/empty.h" #include "opal/memoryhooks/memory.h" #include "opal/util/output.h" +#include "opal/util/show_help.h" #include "opal/mca/memory/linux/memory_linux.h" #undef opal_memory_changed @@ -93,7 +103,12 @@ opal_memory_linux_component_t mca_memory_linux_component = { end up using ummunotify support. */ NULL, opal_memory_base_component_register_empty, - opal_memory_base_component_deregister_empty + opal_memory_base_component_deregister_empty, +#if MEMORY_LINUX_MALLOC_ALIGN_ENABLED + opal_memory_linux_malloc_set_alignment, +#else + opal_memory_base_component_set_alignment_empty, +#endif }, /* Component-specific data, filled in later (compiler will 0/NULL @@ -103,6 +118,26 @@ opal_memory_linux_component_t mca_memory_linux_component = { static bool ptmalloc2_available = MEMORY_LINUX_PTMALLOC2; static bool ummunotify_available = MEMORY_LINUX_UMMUNOTIFY; +#if MEMORY_LINUX_MALLOC_ALIGN_ENABLED + +static void *(*prev_malloc_hook)(size_t, const void *); + +/* This is a memory allocator hook. The purpose of this is to make + * every malloc aligned. + * There two basic cases here: + * + * 1. Memory manager for Open MPI is enabled. Then memalign below will + * be overridden by __memalign_hook which is set to + * opal_memory_linux_memalign_hook. Thus, _malloc_hook is going to + * use opal_memory_linux_memalign_hook. + * + * 2. No memory manager support. The memalign below is just regular glibc + * memalign which will be called through __malloc_hook instead of malloc. + */ +static void *_opal_memory_linux_malloc_align_hook(size_t sz, const void* caller); +#endif /* MEMORY_LINUX_MALLOC_ALIGN_ENABLED */ + + /* * Register MCA params */ @@ -165,6 +200,53 @@ static int linux_register(void) OPAL_INFO_LVL_3, MCA_BASE_VAR_SCOPE_READONLY, &opal_memory_linux_disable); + if (0 > ret) { + return ret; + } + +#if MEMORY_LINUX_MALLOC_ALIGN_ENABLED + mca_memory_linux_component.use_memalign = -1; + ret = mca_base_component_var_register(&mca_memory_linux_component.super.memoryc_version, + "memalign", + "[64 | 32 | 0] - Enable memory alignment for all malloc calls (default: disabled).", + MCA_BASE_VAR_TYPE_INT, + NULL, + 0, + 0, + OPAL_INFO_LVL_5, + MCA_BASE_VAR_SCOPE_READONLY, + &mca_memory_linux_component.use_memalign); + if (0 > ret) { + return ret; + } + + mca_memory_linux_component.memalign_threshold = 12288; + ret = mca_base_component_var_register(&mca_memory_linux_component.super.memoryc_version, + "memalign_threshold", + "Allocating memory more than memory_linux_memalign_threshold" + "bytes will automatically be aligned to the value of memory_linux_memalign bytes." + "(default: 12288)", + MCA_BASE_VAR_TYPE_SIZE_T, + NULL, + 0, + 0, + OPAL_INFO_LVL_5, + MCA_BASE_VAR_SCOPE_READONLY, + &mca_memory_linux_component.memalign_threshold); + if (0 > ret) { + return ret; + } + + if (mca_memory_linux_component.use_memalign != -1 + && mca_memory_linux_component.use_memalign != 32 + && mca_memory_linux_component.use_memalign != 64 + && mca_memory_linux_component.use_memalign != 0){ + opal_show_help("help-opal-memory-linux.txt", "invalid mca param value", + true, "Wrong memalign parameter value. Allowed values: 64, 32, 0.", + "memory_linux_memalign is reset to 32"); + mca_memory_linux_component.use_memalign = 32; + } +#endif /* MEMORY_LINUX_MALLOC_ALIGN_ENABLED */ return (0 > ret) ? ret : OPAL_SUCCESS; } @@ -191,7 +273,7 @@ static int linux_open(void) if (mca_memory_linux_component.verbose_level >= 10) { opal_output(0, "memory:linux: ummunotify successfully initialized; we'll use that"); } - return OPAL_SUCCESS; + goto done; } if (mca_memory_linux_component.verbose_level >= 10) { opal_output(0, "memory:linux: ummunotify failed to initialize"); @@ -209,7 +291,7 @@ static int linux_open(void) if (mca_memory_linux_component.verbose_level >= 10) { opal_output(0, "memory:linux: ptmalloc2 successfully initialized; we'll use that"); } - return OPAL_SUCCESS; + goto done; } if (mca_memory_linux_component.verbose_level >= 10) { opal_output(0, "memory:linux: ptmalloc2 failed to initialize"); @@ -225,12 +307,36 @@ static int linux_open(void) opal_output(0, "memory:linux: no memory hooks available in this process"); } return OPAL_ERR_NOT_AVAILABLE; + +done: + +#if MEMORY_LINUX_MALLOC_ALIGN_ENABLED + /* save original call */ + prev_malloc_hook = NULL; + + if (mca_memory_linux_component.use_memalign > 0 && + (opal_mem_hooks_support_level() & + (OPAL_MEMORY_FREE_SUPPORT | OPAL_MEMORY_CHUNK_SUPPORT)) != 0) { + prev_malloc_hook = __malloc_hook; + __malloc_hook = _opal_memory_linux_malloc_align_hook; + } +#endif /* MEMORY_LINUX_MALLOC_ALIGN_ENABLED */ + + return OPAL_SUCCESS; } static int linux_close(void) { int v = mca_memory_linux_component.verbose_level; +#if MEMORY_LINUX_MALLOC_ALIGN_ENABLED + /* restore original call */ + if (prev_malloc_hook) { + __malloc_hook = prev_malloc_hook; + prev_malloc_hook = NULL; + } +#endif /* MEMORY_LINUX_MALLOC_ALIGN_ENABLED */ + #if MEMORY_LINUX_UMMUNOTIFY if (ummunotify_opened) { if (v >= 10) { @@ -252,3 +358,32 @@ static int linux_close(void) return OPAL_SUCCESS; } + +#if MEMORY_LINUX_MALLOC_ALIGN_ENABLED +void opal_memory_linux_malloc_set_alignment(int use_memalign, size_t memalign_threshold) +{ + /* ignore cases when this capability is enabled explicitly using + * mca variables + */ + if ((NULL == prev_malloc_hook) && (-1 == mca_memory_linux_component.use_memalign)) { + if (use_memalign == 0 || use_memalign == 32 || use_memalign == 64) { + mca_memory_linux_component.use_memalign = use_memalign; + mca_memory_linux_component.memalign_threshold = memalign_threshold; + if ((opal_mem_hooks_support_level() & + (OPAL_MEMORY_FREE_SUPPORT | OPAL_MEMORY_CHUNK_SUPPORT)) != 0) { + prev_malloc_hook = __malloc_hook; + __malloc_hook = _opal_memory_linux_malloc_align_hook; + } + } + } +} + +static void *_opal_memory_linux_malloc_align_hook(size_t sz, const void* caller) +{ + if (sz < mca_memory_linux_component.memalign_threshold) { + return prev_malloc_hook(sz, caller); + } else { + return memalign(mca_memory_linux_component.use_memalign, sz); + } +} +#endif /* MEMORY_LINUX_MALLOC_ALIGN_ENABLED */ diff --git a/opal/mca/memory/malloc_solaris/memory_malloc_solaris_component.c b/opal/mca/memory/malloc_solaris/memory_malloc_solaris_component.c index 0387dc66d4..81f2a1e806 100644 --- a/opal/mca/memory/malloc_solaris/memory_malloc_solaris_component.c +++ b/opal/mca/memory/malloc_solaris/memory_malloc_solaris_component.c @@ -11,10 +11,15 @@ * All rights reserved. * Copyright (c) 2007-2011 Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2009-2011 Cisco Systems, Inc. All rights reserved. + * Copyright (c) 2016 Research Organization for Information Science + * and Technology (RIST). All rights reserved. + * Copyright (c) 2015 Mellanox Technologies, Inc. + * All rights reserved. + * * $COPYRIGHT$ - * + * * Additional copyrights may follow - * + * * $HEADER$ */ @@ -68,6 +73,7 @@ const opal_memory_base_component_2_0_0_t mca_memory_malloc_solaris_component = { NULL, opal_memory_base_component_register_empty, opal_memory_base_component_deregister_empty, + opal_memory_base_component_set_alignment_empty, }; /* diff --git a/opal/mca/memory/memory.h b/opal/mca/memory/memory.h index 89989506d1..d47c54cf0e 100644 --- a/opal/mca/memory/memory.h +++ b/opal/mca/memory/memory.h @@ -10,10 +10,15 @@ * Copyright (c) 2004-2005 The Regents of the University of California. * All rights reserved. * Copyright (c) 2009 Cisco Systems, Inc. All rights reserved. + * Copyright (c) 2016 Research Organization for Information Science + * and Technology (RIST). All rights reserved. + * Copyright (c) 2016 Mellanox Technologies, Inc. + * All rights reserved. + * * $COPYRIGHT$ - * + * * Additional copyrights may follow - * + * * $HEADER$ */ @@ -89,7 +94,7 @@ typedef int (*opal_memory_base_component_register_fn_t)(void *base, /** - * Prototype for a function that is the opposite of + * Prototype for a function that is the opposite of * opal_memory_base_component_register_fn_t: this function is invoked * when Open MPI stops to "caring" about a specific memory region. * That is, Open MPI declares that it no longer wants to be notified @@ -108,6 +113,12 @@ typedef int (*opal_memory_base_component_deregister_fn_t)(void *base, uint64_t cookie); +/** + * Prototype for a function that set the memory alignment + */ +typedef void (*opal_memory_base_component_set_alignment_fn_t)(int use_memalign, + size_t memalign_threshold); + /** * Structure for memory components. */ @@ -129,6 +140,8 @@ typedef struct opal_memory_base_component_2_0_0_t { /** Function invoked when Open MPI stops "caring" about a specific memory region */ opal_memory_base_component_deregister_fn_t memoryc_deregister; + /** Function invoked in order to set malloc'ed memory alignment */ + opal_memory_base_component_set_alignment_fn_t memoryc_set_alignment; } opal_memory_base_component_2_0_0_t; OPAL_DECLSPEC extern opal_memory_base_component_2_0_0_t *opal_memory; From 9baa31440d79d3058f022fe9add2183bcdc78c0c Mon Sep 17 00:00:00 2001 From: Gilles Gouaillardet Date: Wed, 2 Mar 2016 14:19:06 +0900 Subject: [PATCH 2/2] memory/linux: make memory_linux_memalign an enum Thanks Igor Ivanov for the review. --- .../memory/linux/help-opal-memory-linux.txt | 7 ----- .../mca/memory/linux/memory_linux_component.c | 27 ++++++++++--------- 2 files changed, 15 insertions(+), 19 deletions(-) diff --git a/opal/mca/memory/linux/help-opal-memory-linux.txt b/opal/mca/memory/linux/help-opal-memory-linux.txt index 9db3123278..0f9db1f4c8 100644 --- a/opal/mca/memory/linux/help-opal-memory-linux.txt +++ b/opal/mca/memory/linux/help-opal-memory-linux.txt @@ -40,10 +40,3 @@ alternate memory hook manager *may* be used instead (if available). Local host: %s UMMU device: %s Error: %s (%d) -# -[invalid mca param value] -WARNING: An invalid MCA parameter value was found for memory/linux -component. - - Problem: %s - Resolution: %s diff --git a/opal/mca/memory/linux/memory_linux_component.c b/opal/mca/memory/linux/memory_linux_component.c index fec41c7b33..b462c20a70 100644 --- a/opal/mca/memory/linux/memory_linux_component.c +++ b/opal/mca/memory/linux/memory_linux_component.c @@ -135,6 +135,14 @@ static void *(*prev_malloc_hook)(size_t, const void *); * memalign which will be called through __malloc_hook instead of malloc. */ static void *_opal_memory_linux_malloc_align_hook(size_t sz, const void* caller); + +static mca_base_var_enum_value_t align_values[] = { + {-1, "disabled"}, + {0, "0"}, + {32, "32"}, + {64, "64"}, + {0, NULL} +}; #endif /* MEMORY_LINUX_MALLOC_ALIGN_ENABLED */ @@ -143,6 +151,9 @@ static void *_opal_memory_linux_malloc_align_hook(size_t sz, const void* caller) */ static int linux_register(void) { +#if MEMORY_LINUX_MALLOC_ALIGN_ENABLED + mca_base_var_enum_t *new_enum; +#endif int ret; /* Information only */ ret = mca_base_component_var_register (&mca_memory_linux_component.super.memoryc_version, @@ -205,17 +216,19 @@ static int linux_register(void) } #if MEMORY_LINUX_MALLOC_ALIGN_ENABLED + (void)mca_base_var_enum_create("memory_linux_memalign", align_values, &new_enum); mca_memory_linux_component.use_memalign = -1; ret = mca_base_component_var_register(&mca_memory_linux_component.super.memoryc_version, "memalign", - "[64 | 32 | 0] - Enable memory alignment for all malloc calls (default: disabled).", + "[64 | 32 | 0] - Enable memory alignment for all malloc calls.", MCA_BASE_VAR_TYPE_INT, - NULL, + new_enum, 0, 0, OPAL_INFO_LVL_5, MCA_BASE_VAR_SCOPE_READONLY, &mca_memory_linux_component.use_memalign); + OBJ_RELEASE(new_enum); if (0 > ret) { return ret; } @@ -236,16 +249,6 @@ static int linux_register(void) if (0 > ret) { return ret; } - - if (mca_memory_linux_component.use_memalign != -1 - && mca_memory_linux_component.use_memalign != 32 - && mca_memory_linux_component.use_memalign != 64 - && mca_memory_linux_component.use_memalign != 0){ - opal_show_help("help-opal-memory-linux.txt", "invalid mca param value", - true, "Wrong memalign parameter value. Allowed values: 64, 32, 0.", - "memory_linux_memalign is reset to 32"); - mca_memory_linux_component.use_memalign = 32; - } #endif /* MEMORY_LINUX_MALLOC_ALIGN_ENABLED */ return (0 > ret) ? ret : OPAL_SUCCESS;