Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
argo
aml
Commits
b83390e0
Commit
b83390e0
authored
May 14, 2020
by
Nicolas Denoyelle
Committed by
Nicolas Denoyelle
May 15, 2020
Browse files
Add basic hwloc areas
parent
9b41ec63
Pipeline
#10478
passed with stages
in 3 minutes and 24 seconds
Changes
13
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
configure.ac
View file @
b83390e0
...
...
@@ -76,6 +76,20 @@ AC_CHECK_HEADERS([numa.h],,[AC_MSG_ERROR([AML requires libnuma headers.])])
AC_CHECK_HEADERS([numaif.h],,[AC_MSG_ERROR([AML requires libnuma headers.])])
AC_CHECK_LIB(numa, mbind,,[AC_MSG_ERROR([AML requires libnuma.])])
# Hwloc support
###############
PKG_CHECK_MODULES([HWLOC], \
[hwloc >= 2.0], \
[have_hwloc=1], \
[have_hwloc=0])
if test "$have_hwloc" == "1"; then
AC_DEFINE([HAVE_HWLOC], [1], "hwloc library with ABI > 2.0 is installed.")
fi
AM_CONDITIONAL([HAVE_HWLOC], [test "$have_hwloc" = "1"])
AC_DEFINE_UNQUOTED([HAVE_HWLOC], [$have_hwloc], [Whether aml support hwloc library calls.])
AC_SUBST([HAVE_HWLOC],[$have_hwloc])
# check doxygen + sphinx for documentation build
################################################
...
...
doc/tutorials/Makefile.am
View file @
b83390e0
...
...
@@ -13,6 +13,12 @@ AM_CFLAGS += $(CUDA_CFLAGS)
AM_LDFLAGS
+=
$(CUDA_LIBS)
endif
if
HAVE_HWLOC
LIBS
+=
$(HWLOC_LIBS)
AM_CFLAGS
+=
$(HWLOC_CFLAGS)
AM_LDFLAGS
+=
$(HWLOC_LIBS)
endif
# valgrind support
@VALGRIND_CHECK_RULES@
...
...
@@ -39,6 +45,10 @@ if HAVE_CUDA
AREA_TESTS
+=
area/0_aml_area_cuda
endif
if
HAVE_HWLOC
AREA_TESTS
+=
area/2_aml_area_hwloc
endif
UNIT_TESTS
=
$(HELLO_TESTS)
$(AREA_TESTS)
$(LAYOUT_TESTS)
$(DMA_TESTS)
$(TILING_TESTS)
check_PROGRAMS
=
$(UNIT_TESTS)
...
...
doc/tutorials/area/2_aml_area_hwloc.c
0 → 100644
View file @
b83390e0
/*******************************************************************************
* Copyright 2019 UChicago Argonne, LLC.
* (c.f. AUTHORS, LICENSE)
*
* This file is part of the AML project.
* For more info, see https://xgitlab.cels.anl.gov/argo/aml
*
* SPDX-License-Identifier: BSD-3-Clause
*******************************************************************************/
#include <aml.h>
#include <aml/area/hwloc.h>
//!\\ You should initialize your own topology instead. @see <hwloc.h>
extern
hwloc_topology_t
aml_topology
;
static
const
size_t
size
=
(
1
<<
22
);
// 4 MB
/**
* Use static hwloc interleave area.
**/
int
static_interleave_area
()
{
void
*
data
=
aml_area_mmap
(
&
aml_area_hwloc_interleave
,
size
,
NULL
);
// Worked ?
if
(
data
==
NULL
)
{
aml_perror
(
"aml_area_mmap"
);
return
1
;
}
// Cleanup
aml_area_munmap
(
&
aml_area_hwloc_interleave
,
data
,
size
);
return
0
;
}
int
main
(
int
argc
,
char
**
argv
)
{
if
(
aml_init
(
&
argc
,
&
argv
)
!=
0
)
return
1
;
if
(
static_interleave_area
()
!=
0
)
goto
err
;
// Cleanup success
aml_finalize
();
return
0
;
// Cleanup error
err:
aml_finalize
();
return
1
;
}
doc/tutorials/area/areas.rst
View file @
b83390e0
...
...
@@ -80,6 +80,34 @@ Now we have an "allocator" of interleaved data.
Here we have allocated 8*4096 bytes of data across system memories.
Hwloc Area
----------
If you compiled AML with hwloc backend support and the supports hwloc library
at runtime, then you can use aml area features built on top of hwloc.
.. code-block:: c
#include <aml/utils/features.h>
#if AML_HAVE_BACKEND_HWLOC == 1
#include <aml/area/hwloc.h>
...
if (aml_support_backends(AML_BACKEND_HWLOC)) {
...
}
...
#endif
The backend provides static areas, e.g for interleaving data on all NUMA nodes:
.. code-block:: c
void *data = aml_area_mmap(&aml_area_hwloc_interleave, size, NULL);
and areas constructor based on hwloc memory binding policies and nodeset.
The backend may require that you provide objects from the current system
topology. Such a topology may be obtained through hwloc API.
CUDA Area
---------
...
...
include/Makefile.am
View file @
b83390e0
...
...
@@ -5,6 +5,10 @@ include_aml_area_HEADERS = \
aml/area/linux.h
\
aml/area/cuda.h
if
HAVE_HWLOC
include_aml_area_HEADERS
+=
aml/area/hwloc.h
endif
include_aml_layoutdir
=
$(includedir)
/aml/layout
include_aml_layout_HEADERS
=
\
aml/layout/native.h
\
...
...
include/aml/area/hwloc.h
0 → 100644
View file @
b83390e0
/*******************************************************************************
* Copyright 2019 UChicago Argonne, LLC.
* (c.f. AUTHORS, LICENSE)
*
* This file is part of the AML project.
* For more info, see https://xgitlab.cels.anl.gov/argo/aml
*
* SPDX-License-Identifier: BSD-3-Clause
******************************************************************************/
#ifndef AML_AREA_HWLOC_H
#define AML_AREA_HWLOC_H
#include <hwloc.h>
#include <hwloc/distances.h>
/**
* @defgroup aml_area_hwloc "AML hwloc Areas"
* @brief Implementation of Areas with features from hwloc library.
*
* Implementation of AML areas with hwloc library.
* This building block relies on hwloc to provide mmap/munmap.
* hwloc areas inherit hwloc portability and provide constructor
* to customize binding of areas.
* This building block also include a static declaration of
* several default areas that can be used out of the box with
* abstract area API.
*
* @code
* #include <aml/area/hwloc.h>
* @endcode
* @see <hwloc.h>
* @see https://www.open-mpi.org/projects/hwloc/doc/v2.0.0/
* @{
**/
/**************************************************************************/
/* aml_area_hwloc */
/**************************************************************************/
// Struct definition
//////////////////////
/** User data stored inside aml hwloc area. **/
struct
aml_area_hwloc_data
{
/** Nodeset where to bind data **/
hwloc_bitmap_t
nodeset
;
/** Memory binding policy **/
hwloc_membind_policy_t
policy
;
};
// Methods
//////////////////////
/**
* Create an area with specific memory binding.
* @param[out] area: A pointer where to store newly created area.
* @param[in] nodeset: The location where to bind memory with this area.
* @param[in] policy: The binding policy of this area.
* @return -AML_ENOMEM if not enough memory was available to create the area.
* @return -AML_ENOTSUP if policy is not supported.
* @return -AML_EDOM if nodeset is out of allowed nodeset.
* @return AML_SUCCESS.
**/
int
aml_area_hwloc_create
(
struct
aml_area
**
area
,
hwloc_bitmap_t
nodeset
,
const
hwloc_membind_policy_t
policy
);
/**
* Free an area obtained with aml_area_hwloc_create().
* @param[in] area: The pointer to area to free.
* The content of the pointer is set to NULL.
**/
void
aml_area_hwloc_destroy
(
struct
aml_area
**
area
);
/**
* Base function for mapping and binding memory.
* It is a wrapper to hwloc_alloc_membind().
* @param[in] data: struct aml_area_hwloc_data* initialized with a binding.
* @param[in] size: The size of memory to query.
* @param[in] opts: ignored.
* @return A pointer to mapped memory region.
* @return NULL on failure with aml_errno se to:
* - AML_ENOMEM if there is not enough memory available to fulfill
* the operation.
* - AML_ENOTSUP if area allocation policy is not supported.
* - AML_FAILURE if binding cannot be enforced.
**/
void
*
aml_area_hwloc_mmap
(
const
struct
aml_area_data
*
data
,
size_t
size
,
struct
aml_area_mmap_options
*
opts
);
/**
* Free memory allocated by aml_area_hwloc_mmap().
* It is a wrapper to hwloc_alloc_free().
* @param[in] data: Unused.
* @param[in] ptr: The memory region to unmap.
* @param[in] size: The size of memory region to unmap.
* @return AML_SUCCESS.
**/
int
aml_area_hwloc_munmap
(
const
struct
aml_area_data
*
data
,
void
*
ptr
,
size_t
size
);
/**
* @brief Check allocation binding against area binding settings.
*
* Check if the data allocated with a aml_area_hwloc is bound
* as expected to memory, i.e it is allocated on allowed NUMA nodes
* and with the good policy.
* @param[in] area: A aml_area_hwloc.
* @param[in] ptr: The data allocated with same area.
* @param[in] size: The data size in Bytes.
* @return 1 if ptr is bound according to area settings.
* @return 0 otherwise.
**/
int
aml_area_hwloc_check_binding
(
struct
aml_area
*
area
,
void
*
ptr
,
size_t
size
);
// static declarations
//////////////////////
/** Operations of aml_area_hwloc **/
extern
struct
aml_area_ops
aml_area_hwloc_ops
;
/** Convenience default area declaration without specific binding. **/
extern
struct
aml_area
aml_area_hwloc_default
;
/**
* Convenience area declaration with binding on every nodes of the
* topology and interleave allocation policy.
**/
extern
struct
aml_area
aml_area_hwloc_interleave
;
/**
* Convenience area declaration with binding on every nodes of the
* topology and firsttouch allocation policy.
**/
extern
struct
aml_area
aml_area_hwloc_firsttouch
;
/**
* @}
**/
#endif // AML_AREA_HWLOC_H
include/aml/utils/features.h.in
View file @
b83390e0
...
...
@@ -27,11 +27,15 @@
#define AML_HAVE_BACKEND_LIBNUMA 1
/** Whether aml had cuda capabilities at compile time **/
#define AML_HAVE_BACKEND_CUDA @HAVE_CUDA@
/** Whether aml had hwloc capabilities at compile time **/
#define AML_HAVE_BACKEND_HWLOC @HAVE_HWLOC@
/** Flag for checking runtime suport for libnuma **/
#define AML_BACKEND_LIBNUMA (1UL<<1)
/** Flag for checking runtime suport for cuda **/
#define AML_BACKEND_CUDA (1UL<<2)
/** Flag for checking runtime suport for hwloc **/
#define AML_BACKEND_HWLOC (1UL<<3)
/**
* Check if a set of backends can be used at runtime.
...
...
src/Makefile.am
View file @
b83390e0
...
...
@@ -85,3 +85,13 @@ libaml_la_SOURCES+=area/cuda.c
# libaml_la_LIBADD+=libamlcuda.la
endif
#############################################
# hwloc sources
if
HAVE_HWLOC
AM_CPPFLAGS
+=
$(HWLOC_CFLAGS)
AM_LDFLAGS
+=
$(HWLOC_LIBS)
libaml_la_SOURCES
+=
area/hwloc.c
endif
src/aml.c
View file @
b83390e0
...
...
@@ -6,12 +6,14 @@
* For more info, see https://xgitlab.cels.anl.gov/argo/aml
*
* SPDX-License-Identifier: BSD-3-Clause
*******************************************************************************/
*******************************************************************************/
#include "aml.h"
#include "config.h"
#include <string.h>
#include "aml.h"
const
int
aml_version_major
=
AML_VERSION_MAJOR
;
const
int
aml_version_minor
=
AML_VERSION_MINOR
;
const
int
aml_version_patch
=
AML_VERSION_PATCH
;
...
...
@@ -19,15 +21,50 @@ const char *aml_version_string = AML_VERSION_STRING;
int
aml_errno
;
#if HAVE_HWLOC == 1
#include <hwloc.h>
hwloc_topology_t
aml_topology
;
hwloc_const_bitmap_t
allowed_nodeset
;
int
aml_topology_init
(
void
)
{
if
(
hwloc_topology_init
(
&
aml_topology
)
==
-
1
)
return
-
1
;
if
(
hwloc_topology_set_flags
(
aml_topology
,
HWLOC_TOPOLOGY_FLAG_THISSYSTEM_ALLOWED_RESOURCES
)
==
-
1
)
return
-
1
;
if
(
hwloc_topology_load
(
aml_topology
)
==
-
1
)
return
-
1
;
return
0
;
}
#endif
int
aml_init
(
int
*
argc
,
char
**
argv
[])
{
// disable warnings
(
void
)
argc
;
(
void
)
argv
;
(
void
)
argc
;
(
void
)
argv
;
// Initialize topology
#if HAVE_HWLOC == 1
int
err_hwloc
;
err_hwloc
=
aml_topology_init
();
if
(
err_hwloc
<
0
)
return
AML_FAILURE
;
allowed_nodeset
=
hwloc_topology_get_allowed_nodeset
(
aml_topology
);
#endif
return
0
;
}
int
aml_finalize
(
void
)
{
// Destroy topology
#if HAVE_HWLOC == 1
hwloc_topology_destroy
(
aml_topology
);
#endif
return
0
;
}
src/area/hwloc.c
0 → 100644
View file @
b83390e0
/*******************************************************************************
* Copyright 2019 UChicago Argonne, LLC.
* (c.f. AUTHORS, LICENSE)
*
* This file is part of the AML project.
* For more info, see https://xgitlab.cels.anl.gov/argo/aml
*
* SPDX-License-Identifier: BSD-3-Clause
******************************************************************************/
#include <sys/mman.h>
#include "aml.h"
#include "aml/area/hwloc.h"
#define HWLOC_BINDING_FLAGS \
(HWLOC_MEMBIND_PROCESS | HWLOC_MEMBIND_NOCPUBIND | \
HWLOC_MEMBIND_BYNODESET | HWLOC_MEMBIND_STRICT)
/**
* Topology used by AML.
* Topology is initalized when calling aml_library_init().
**/
extern
hwloc_topology_t
aml_topology
;
extern
hwloc_const_bitmap_t
allowed_nodeset
;
/**************************************************************************/
/* aml_area_hwloc */
/**************************************************************************/
static
int
aml_area_hwloc_init
(
struct
aml_area
*
area
,
hwloc_bitmap_t
nodeset
,
const
hwloc_membind_policy_t
policy
)
{
struct
aml_area_hwloc_data
*
d
=
(
struct
aml_area_hwloc_data
*
)
area
->
data
;
// Check support
const
struct
hwloc_topology_support
*
sup
=
hwloc_topology_get_support
(
aml_topology
);
if
(
policy
==
HWLOC_MEMBIND_BIND
&&
!
sup
->
membind
->
bind_membind
)
return
-
AML_ENOTSUP
;
if
(
policy
==
HWLOC_MEMBIND_FIRSTTOUCH
&&
!
sup
->
membind
->
firsttouch_membind
)
return
-
AML_ENOTSUP
;
if
(
policy
==
HWLOC_MEMBIND_INTERLEAVE
&&
!
sup
->
membind
->
interleave_membind
)
return
-
AML_ENOTSUP
;
if
(
policy
==
HWLOC_MEMBIND_NEXTTOUCH
&&
!
sup
->
membind
->
nexttouch_membind
)
return
-
AML_ENOTSUP
;
// Check nodeset does not include unallowed nodes
if
(
nodeset
&&
!
hwloc_bitmap_isincluded
(
nodeset
,
allowed_nodeset
))
return
-
AML_EDOM
;
// Set area nodeset and policy
if
(
nodeset
==
NULL
)
d
->
nodeset
=
hwloc_bitmap_dup
(
allowed_nodeset
);
else
d
->
nodeset
=
hwloc_bitmap_dup
(
nodeset
);
d
->
policy
=
policy
;
return
AML_SUCCESS
;
}
int
aml_area_hwloc_create
(
struct
aml_area
**
area
,
hwloc_bitmap_t
nodeset
,
const
hwloc_membind_policy_t
policy
)
{
int
err
=
AML_SUCCESS
;
struct
aml_area
*
a
;
struct
aml_area_hwloc_data
*
data
;
a
=
AML_INNER_MALLOC
(
struct
aml_area
,
struct
aml_area_hwloc_data
);
if
(
a
==
NULL
)
return
-
AML_ENOMEM
;
a
->
ops
=
&
aml_area_hwloc_ops
;
data
=
AML_INNER_MALLOC_GET_FIELD
(
a
,
2
,
struct
aml_area
,
struct
aml_area_hwloc_data
);
a
->
data
=
(
struct
aml_area_data
*
)
data
;
err
=
aml_area_hwloc_init
(
a
,
nodeset
,
policy
);
if
(
err
!=
AML_SUCCESS
)
{
free
(
a
);
return
err
;
}
*
area
=
a
;
return
AML_SUCCESS
;
}
void
aml_area_hwloc_destroy
(
struct
aml_area
**
area
)
{
if
(
area
==
NULL
||
*
area
==
NULL
)
return
;
struct
aml_area_hwloc_data
*
data
=
(
struct
aml_area_hwloc_data
*
)(
*
area
)
->
data
;
hwloc_bitmap_free
(
data
->
nodeset
);
free
(
*
area
);
*
area
=
NULL
;
}
void
*
aml_area_hwloc_mmap
(
const
struct
aml_area_data
*
data
,
size_t
size
,
struct
aml_area_mmap_options
*
opts
)
{
(
void
)
opts
;
struct
aml_area_hwloc_data
*
hwloc_data
=
(
struct
aml_area_hwloc_data
*
)
data
;
hwloc_const_bitmap_t
nodeset
=
hwloc_data
->
nodeset
==
NULL
?
allowed_nodeset
:
hwloc_data
->
nodeset
;
void
*
p
=
hwloc_alloc_membind
(
aml_topology
,
size
,
nodeset
,
hwloc_data
->
policy
,
HWLOC_BINDING_FLAGS
);
if
(
p
==
NULL
)
{
if
(
errno
==
EINVAL
)
aml_errno
=
AML_EINVAL
;
if
(
errno
==
ENOSYS
)
aml_errno
=
AML_ENOTSUP
;
if
(
errno
==
EXDEV
)
aml_errno
=
AML_FAILURE
;
if
(
errno
==
ENOMEM
)
aml_errno
=
AML_ENOMEM
;
return
NULL
;
}
return
p
;
}
int
aml_area_hwloc_munmap
(
const
struct
aml_area_data
*
data
,
void
*
ptr
,
size_t
size
)
{
(
void
)
data
;
hwloc_free
(
aml_topology
,
ptr
,
size
);
return
AML_SUCCESS
;
}
int
aml_area_hwloc_check_binding
(
struct
aml_area
*
area
,
void
*
ptr
,
size_t
size
)
{
int
err
;
hwloc_membind_policy_t
policy
;
hwloc_bitmap_t
nodeset
;
struct
aml_area_hwloc_data
*
bind
=
(
struct
aml_area_hwloc_data
*
)
area
->
data
;
nodeset
=
hwloc_bitmap_alloc
();
if
(
nodeset
==
NULL
)
return
-
AML_ENOMEM
;
err
=
hwloc_get_area_membind
(
aml_topology
,
ptr
,
size
,
nodeset
,
&
policy
,
HWLOC_BINDING_FLAGS
);
if
(
err
<
0
)
{
err
=
AML_EINVAL
;
goto
out
;
}
err
=
1
;
if
(
policy
!=
bind
->
policy
&&
bind
->
policy
!=
HWLOC_MEMBIND_DEFAULT
&&
bind
->
policy
!=
HWLOC_MEMBIND_MIXED
)
err
=
0
;
if
(
!
hwloc_bitmap_isequal
(
nodeset
,
bind
->
nodeset
))
err
=
0
;
out:
hwloc_bitmap_free
(
nodeset
);
return
err
;
}
/**
* Static declaration of an area.
* No check is performed to enforced availability of policies and nodeset.
* If bad values are provided area function call will return
* an error.
* @param[in] name: The area instance name.
* @param[in] bitmap: The nodeset to set inside area (hwloc_bitmap_t).
* Can be NULL.
* @param[in] bind_policy: The memory allocation policy
* (hwloc_membind_policy_t).
**/
#define AML_AREA_HWLOC_DECL(name, bitmap, bind_policy) \
struct aml_area_hwloc_data __##name##_data = {.nodeset = bitmap, \
.policy = bind_policy}; \
struct aml_area name = { \
.ops = &aml_area_hwloc_ops, \
.data = (struct aml_area_data *)&__##name##_data}
struct
aml_area_ops
aml_area_hwloc_ops
=
{
.
mmap
=
aml_area_hwloc_mmap
,
.
munmap
=
aml_area_hwloc_munmap
,
.
fprintf
=
NULL
,
};
AML_AREA_HWLOC_DECL
(
aml_area_hwloc_default
,
NULL
,
HWLOC_MEMBIND_DEFAULT
);
AML_AREA_HWLOC_DECL
(
aml_area_hwloc_interleave
,
NULL
,
HWLOC_MEMBIND_INTERLEAVE
);
AML_AREA_HWLOC_DECL
(
aml_area_hwloc_firsttouch
,
NULL
,
HWLOC_MEMBIND_FIRSTTOUCH
);
src/utils/features.c
View file @
b83390e0
...
...
@@ -6,14 +6,19 @@
* For more info, see https://xgitlab.cels.anl.gov/argo/aml
*
* SPDX-License-Identifier: BSD-3-Clause
*******************************************************************************/
*******************************************************************************/
#include "aml/utils/features.h"
#include "config.h"
#include "aml/utils/features.h"
#if HAVE_CUDA == 1
#include <cuda.h>
#include <cuda_runtime.h>
#endif
#if HAVE_HWLOC == 1
#include <hwloc.h>
extern
hwloc_topology_t
aml_topology
;
#endif
static
int
aml_support_cuda
(
void
)
{
...
...
@@ -29,6 +34,21 @@ static int aml_support_cuda(void)
#endif
}
static
int
aml_support_hwloc
(
void
)
{
#if HAVE_HWLOC == 0
return
0
;
#else
const
struct
hwloc_topology_support
*
sup
=
hwloc_topology_get_support
(
aml_topology
);
if
(
!
sup
->
discovery
->
numa
||
!
sup
->
discovery
->
numa_memory
)