diff --git a/arcane/src/arcane/accelerator/core/AcceleratorRuntimeInitialisationInfo.cc b/arcane/src/arcane/accelerator/core/AcceleratorRuntimeInitialisationInfo.cc index 13b6d80cb..5b2eda7a2 100644 --- a/arcane/src/arcane/accelerator/core/AcceleratorRuntimeInitialisationInfo.cc +++ b/arcane/src/arcane/accelerator/core/AcceleratorRuntimeInitialisationInfo.cc @@ -16,6 +16,7 @@ #include "arcane/utils/ITraceMng.h" #include "arcane/utils/String.h" #include "arcane/utils/Property.h" +#include "arcane/utils/MemoryUtils.h" #include "arcane/accelerator/core/Runner.h" #include "arcane/accelerator/core/DeviceId.h" @@ -175,6 +176,7 @@ arcaneInitializeRunner(Accelerator::Runner& runner,ITraceMng* tm, if (policy==eExecutionPolicy::None) ARCANE_FATAL("Invalid policy eExecutionPolicy::None"); tm->info() << "AcceleratorRuntime=" << accelerator_runtime; + tm->info() << "DefaultDataAllocator MemoryResource=" << MemoryUtils::getDefaultDataMemoryResource(); if (impl::isAcceleratorPolicy(policy)){ tm->info() << "Using accelerator runtime=" << policy << " device=" << acc_info.deviceId(); runner.initialize(policy,acc_info.deviceId()); diff --git a/arcane/src/arcane/impl/ArcaneMain.cc b/arcane/src/arcane/impl/ArcaneMain.cc index df6ba9f74..951f3c126 100644 --- a/arcane/src/arcane/impl/ArcaneMain.cc +++ b/arcane/src/arcane/impl/ArcaneMain.cc @@ -35,6 +35,8 @@ #include "arcane/utils/CommandLineArguments.h" #include "arcane/utils/ApplicationInfo.h" #include "arcane/utils/TestLogger.h" +#include "arcane/utils/MemoryUtils.h" +#include "arcane/utils/internal/MemoryUtilsInternal.h" #include "arcane/core/ArcaneException.h" #include "arcane/core/IMainFactory.h" @@ -1113,7 +1115,7 @@ _checkAutoDetectMPI() * * \retval 0 si tout est OK * - * \note Ne pas appeler directement cette méthode mais + * \note Il ne faut pas appeler directement cette méthode mais * passer par ArcaneMainAutoDetectHelper. */ int ArcaneMain:: @@ -1130,7 +1132,7 @@ _checkAutoDetectAccelerator(bool& has_accelerator) return 0; try { - // Pour l'instant, seul les runtimes 'cuda' et 'hip' sont autorisés + // Pour l'instant, seul les runtimes 'cuda', 'hip' et 'sycl' sont autorisés if (runtime_name != "cuda" && runtime_name != "hip" && runtime_name != "sycl") ARCANE_FATAL("Invalid accelerator runtime '{0}'. Only 'cuda', 'hip' or 'sycl' is allowed", runtime_name); @@ -1165,8 +1167,20 @@ _checkAutoDetectAccelerator(bool& has_accelerator) if (!verbose_str.null()) runtime_info.setVerbose(true); + // Par défaut utilise la mémoire unifiée pour les données. + // Le runtime accélérateur pourra changer cela. + MemoryUtils::setDefaultDataMemoryResource(eMemoryResource::UnifiedMemory); + (*my_functor)(runtime_info); has_accelerator = true; + + // Permet de surcharger le choix de l'allocateur des données + String data_allocator_str = Arcane::platform::getEnvironmentVariable("ARCANE_DEFAULT_DATA_MEMORY_RESOURCE"); + if (!data_allocator_str.null()){ + eMemoryResource v = MemoryUtils::getMemoryResourceFromName(data_allocator_str); + if (v!=eMemoryResource::Unknown) + MemoryUtils::setDefaultDataMemoryResource(v); + } } catch (const Exception& ex) { return arcanePrintArcaneException(ex, nullptr); diff --git a/arcane/src/arcane/tests/CMakeLists.txt b/arcane/src/arcane/tests/CMakeLists.txt index c8c3beb0f..ce6218ef6 100644 --- a/arcane/src/arcane/tests/CMakeLists.txt +++ b/arcane/src/arcane/tests/CMakeLists.txt @@ -1,4 +1,4 @@ -set(TEST_DIRS . anyitem dof inout) +set(TEST_DIRS . anyitem dof inout) set(TEST_LIBS ${ARCANE_ADDITIONNAL_TEST_LIBRARIES}) if(MPI_FOUND AND NOT WIN32) @@ -365,6 +365,7 @@ if (ARCANE_HAS_ACCELERATOR_API) arcane_add_test_sequential(standalone_accelerator_testsum dummy.arc "-A,StandaloneAcceleratorMethod=TestSum") arcane_add_test_sequential(standalone_accelerator_testbinop dummy.arc "-A,StandaloneAcceleratorMethod=TestBinOp") arcane_add_accelerator_test_sequential(standalone_accelerator_testsum dummy.arc "-A,StandaloneAcceleratorMethod=TestSum") + arcane_add_accelerator_test_sequential(standalone_accelerator_testsum_hostpinned dummy.arc "-A,StandaloneAcceleratorMethod=TestSum" "-We,ARCANE_DEFAULT_DATA_MEMORY_RESOURCE,HostPinned") arcane_add_accelerator_test_sequential(standalone_accelerator_testbinop dummy.arc "-A,StandaloneAcceleratorMethod=TestBinOp") arcane_add_accelerator_test_sequential(standalone_accelerator_testemptykernel dummy.arc "-A,StandaloneAcceleratorMethod=TestEmptyKernel") endif() diff --git a/arcane/src/arcane/utils/MemoryUtils.cc b/arcane/src/arcane/utils/MemoryUtils.cc index c05835340..725063036 100644 --- a/arcane/src/arcane/utils/MemoryUtils.cc +++ b/arcane/src/arcane/utils/MemoryUtils.cc @@ -13,9 +13,10 @@ #include "arcane/utils/MemoryUtils.h" -#include "arcane/utils/PlatformUtils.h" +#include "arcane/utils/FatalErrorException.h" #include "arcane/utils/MemoryAllocator.h" #include "arcane/utils/IMemoryRessourceMng.h" +#include "arcane/utils/String.h" #include "arcane/utils/internal/IMemoryRessourceMngInternal.h" #include "arcane/utils/internal/MemoryUtilsInternal.h" #include "arcane/utils/internal/MemoryResourceMng.h" @@ -31,11 +32,54 @@ namespace IMemoryAllocator* global_accelerator_host_memory_allocator = nullptr; MemoryResourceMng global_default_data_memory_resource_mng; IMemoryRessourceMng* global_data_memory_resource_mng = nullptr; + eMemoryResource global_data_memory_resource = eMemoryResource::Host; } // namespace /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ +eMemoryResource MemoryUtils:: +getDefaultDataMemoryResource() +{ + return global_data_memory_resource; +} + +/*---------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ + +void MemoryUtils:: +setDefaultDataMemoryResource(eMemoryResource v) +{ + global_data_memory_resource = v; +} + +/*---------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ + +eMemoryResource MemoryUtils:: +getMemoryResourceFromName(const String& name) +{ + eMemoryResource v = eMemoryResource::Unknown; + if (name.null()) + return v; + if (name == "Device") + v = eMemoryResource::Device; + else if (name == "Host") + v = eMemoryResource::Host; + else if (name == "HostPinned") + v = eMemoryResource::HostPinned; + else if (name == "UnifiedMemory") + v = eMemoryResource::UnifiedMemory; + else + ARCANE_FATAL("Invalid name '{0}' for memory resource. Valid names are " + "'Device', 'Host', 'HostPinned' or 'UnifieMemory'.", + name); + return v; +} + +/*---------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ + IMemoryRessourceMng* MemoryUtils:: setDataMemoryResourceMng(IMemoryRessourceMng* mng) { @@ -63,7 +107,7 @@ getDataMemoryResourceMng() IMemoryAllocator* MemoryUtils:: getDefaultDataAllocator() { - return getDataMemoryResourceMng()->getAllocator(eMemoryResource::UnifiedMemory); + return getDataMemoryResourceMng()->getAllocator(getDefaultDataMemoryResource()); } /*---------------------------------------------------------------------------*/ diff --git a/arcane/src/arcane/utils/MemoryUtils.h b/arcane/src/arcane/utils/MemoryUtils.h index 004cb5128..f70d59f49 100644 --- a/arcane/src/arcane/utils/MemoryUtils.h +++ b/arcane/src/arcane/utils/MemoryUtils.h @@ -29,29 +29,49 @@ namespace Arcane::MemoryUtils /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /*! - * \brief Allocateur par défaut pour les données. + * \brief Ressource mémoire utilisée par l'allocateur par défaut pour les données. * - * Si un runtime accélérateur est initialisé, l'allocateur retourné permet - * d'allouer en mémoire unifiée et donc la zone allouée sera accessible à la - * fois sur l'accélérateur et sur l'hôte. Sinon, retourne un allocateur - * aligné. + * Par défaut, si un runtime accélérateur est initialisé, la ressource + * associé est eMemoryResource::UnifiedMemory. Sinon, il s'agit de + * eMemoryResource::Host. * - * Il est garanti que l'alignement est au moins celui retourné par - * AlignedMemoryAllocator::Simd(). + * \sa getDefaultDataAllocator(); */ -extern "C++" ARCANE_UTILS_EXPORT IMemoryAllocator* -getDefaultDataAllocator(); +extern "C++" ARCANE_UTILS_EXPORT eMemoryResource +getDefaultDataMemoryResource(); +/*---------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ /*! - * \brief Retourne l'allocateur sur l'hôte ou sur le device. + * \brief Retourne la ressource mémoire par son nom. * - * Si un runtime accélérateur est initialisé, l'allocateur retourné permet - * d'allouer en utilisant la mémoire de l'accélérateur par défaut - * (eMemoryResource::Device). Sinon, utilise l'allocateur de l'hôte - * (eMemoryResource::Host). + * Le nom correspond au nom de la valeur de l'énumération (par exemple + * 'Device' pour eMemoryResource::Device. + * + * Si \a name est nul, retourn eMemoryResource::Unknown. + * Si \a name ne correspondant pas à une valeur valide, lève une exception. + */ +extern "C++" ARCANE_UTILS_EXPORT eMemoryResource +getMemoryResourceFromName(const String& name); + +/*---------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ +/*! + * \brief Allocateur par défaut pour les données. + * + * L'allocateur par défaut pour les données est un allocateur qui permet + * d'accéder à la zone mémoire à la fois par l'hôte et l'accélérateur. + * + * Il est possible de récupérer la ressource mémoire associée via + * getDefaultDataMemoryResource(); + * + * Cet appel est équivalent à getAllocator(getDefaultDataMemoryResource()). + * + * Il est garanti que l'alignement est au moins celui retourné par + * AlignedMemoryAllocator::Simd(). */ extern "C++" ARCANE_UTILS_EXPORT IMemoryAllocator* -getDeviceOrHostAllocator(); +getDefaultDataAllocator(); /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ @@ -65,6 +85,19 @@ getDeviceOrHostAllocator(); extern "C++" ARCANE_UTILS_EXPORT MemoryAllocationOptions getDefaultDataAllocator(eMemoryLocationHint hint); +/*---------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ +/*! + * \brief Retourne l'allocateur sur l'hôte ou sur le device. + * + * Si un runtime accélérateur est initialisé, l'allocateur retourné permet + * d'allouer en utilisant la mémoire de l'accélérateur par défaut + * (eMemoryResource::Device). Sinon, utilise l'allocateur de l'hôte + * (eMemoryResource::Host). + */ +extern "C++" ARCANE_UTILS_EXPORT IMemoryAllocator* +getDeviceOrHostAllocator(); + /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /*! diff --git a/arcane/src/arcane/utils/internal/MemoryUtilsInternal.h b/arcane/src/arcane/utils/internal/MemoryUtilsInternal.h index f46c2e1a3..867ba6d26 100644 --- a/arcane/src/arcane/utils/internal/MemoryUtilsInternal.h +++ b/arcane/src/arcane/utils/internal/MemoryUtilsInternal.h @@ -56,6 +56,17 @@ getDataMemoryResourceMng(); extern "C++" ARCANE_UTILS_EXPORT IMemoryAllocator* setAcceleratorHostMemoryAllocator(IMemoryAllocator* a); +/*---------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ +/*! + * \brief Positionne la ressource mémoire utilisée pour l'allocateur + * mémoire des données. + * + * \sa getDefaultDataMemoryResource(); + */ +extern "C++" ARCANE_UTILS_EXPORT void +setDefaultDataMemoryResource(eMemoryResource mem_resource); + /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ diff --git a/arcane/src/arcane/utils/tests/TestMemory.cc b/arcane/src/arcane/utils/tests/TestMemory.cc index df674d707..b11ab7803 100644 --- a/arcane/src/arcane/utils/tests/TestMemory.cc +++ b/arcane/src/arcane/utils/tests/TestMemory.cc @@ -12,6 +12,7 @@ #include "arcane/utils/Exception.h" #include "arcane/utils/MemoryUtils.h" #include "arcane/utils/NumericTypes.h" +#include "arcane/utils/internal/MemoryUtilsInternal.h" #include @@ -173,6 +174,28 @@ TEST(Memory, Basic) } } +/*---------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ +namespace +{ +void _checkSetDataMemoryResource(const String& name, eMemoryResource expected_mem_resource) +{ + eMemoryResource v = MemoryUtils::getMemoryResourceFromName(name); + ASSERT_EQ(v, expected_mem_resource); + MemoryUtils::setDefaultDataMemoryResource(v); + eMemoryResource v2 = MemoryUtils::getDefaultDataMemoryResource(); + ASSERT_EQ(v2, expected_mem_resource); +} +} // namespace + +TEST(Memory, Allocator) +{ + _checkSetDataMemoryResource("Device", eMemoryResource::Device); + _checkSetDataMemoryResource("HostPinned", eMemoryResource::HostPinned); + _checkSetDataMemoryResource("Host", eMemoryResource::Host); + _checkSetDataMemoryResource("UnifiedMemory", eMemoryResource::UnifiedMemory); +} + /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/