14#include "arcane/accelerator/sycl/SyclAccelerator.h"
15#include "arcane/accelerator/sycl/internal/SyclAcceleratorInternal.h"
17#include "arccore/base/PlatformUtils.h"
18#include "arccore/base/NotSupportedException.h"
19#include "arccore/base/FatalErrorException.h"
20#include "arccore/base/NotImplementedException.h"
22#include "arccore/common/IMemoryResourceMng.h"
23#include "arccore/common/internal/IMemoryResourceMngInternal.h"
25#include "arcane/utils/internal/MemoryUtilsInternal.h"
27#include "arcane/accelerator/core/RunQueueBuildInfo.h"
28#include "arcane/accelerator/core/Memory.h"
29#include "arcane/accelerator/core/DeviceInfoList.h"
30#include "arcane/accelerator/core/RunQueue.h"
31#include "arcane/accelerator/core/DeviceMemoryInfo.h"
32#include "arcane/accelerator/core/NativeStream.h"
33#include "arcane/accelerator/core/internal/IRunnerRuntime.h"
34#include "arcane/accelerator/core/internal/RegisterRuntimeInfo.h"
35#include "arcane/accelerator/core/internal/IRunQueueStream.h"
36#include "arcane/accelerator/core/internal/IRunQueueEventImpl.h"
40namespace Arcane::Accelerator::Sycl
43using namespace Arccore;
45#define ARCANE_SYCL_FUNC_NOT_HANDLED \
46 std::cout << "WARNING: SYCL: function not handled " << A_FUNCINFO << "\n"
53class SyclRunQueueStream
59 ~SyclRunQueueStream()
override
67 return m_runtime->notifyBeginLaunchKernel();
71 return m_runtime->notifyEndLaunchKernel();
75 m_sycl_stream->wait_and_throw();
79 m_sycl_stream->wait();
84 auto source_bytes = args.source().
bytes();
85 m_sycl_stream->memcpy(args.destination().
data(), source_bytes.data(),
92 auto source_bytes = args.source().bytes();
93 Int64 nb_byte = source_bytes.size();
96 m_sycl_stream->prefetch(source_bytes.data(), nb_byte);
107 sycl::event last_event;
109 last_event = *(
reinterpret_cast<sycl::event*
>(sycl_event_ptr));
110 m_last_command_event = last_event;
115 static sycl::async_handler _getAsyncHandler()
117 auto err_handler = [](
const sycl::exception_list& exceptions) {
118 std::ostringstream ostr;
119 ostr <<
"Error in SYCL runtime\n";
120 for (
const std::exception_ptr& e : exceptions) {
122 std::rethrow_exception(e);
124 catch (
const sycl::exception& e) {
125 ostr <<
"SYCL exception: " << e.what() <<
"\n";
138 sycl::queue& trueStream()
const
140 return *m_sycl_stream;
146 std::unique_ptr<sycl::queue> m_sycl_stream;
147 sycl::event m_last_command_event;
153class SyclRunQueueEvent
158 explicit SyclRunQueueEvent([[maybe_unused]]
bool has_timer)
161 ~SyclRunQueueEvent()
override
173#if defined(__ADAPTIVECPP__)
174 m_recorded_stream = stream;
176#elif defined(__INTEL_LLVM_COMPILER)
192#if defined(__ADAPTIVECPP__)
194 m_sycl_event.wait(rq->trueStream().get_wait_list());
195#elif defined(__INTEL_LLVM_COMPILER)
196 std::vector<sycl::event> events;
197 events.push_back(m_sycl_event);
199 rq->trueStream().ext_oneapi_submit_barrier(events);
205 Int64 elapsedTime([[maybe_unused]] IRunQueueEventImpl* start_event)
final
210 sycl::event
event = (
static_cast<SyclRunQueueEvent*
>(start_event))->m_sycl_event;
212 if (event==sycl::event())
215 bool is_submitted =
event.get_info<sycl::info::event::command_execution_status>() == sycl::info::event_command_status::complete;
218 Int64 start =
event.get_profiling_info<sycl::info::event_profiling::command_start>();
219 Int64 end =
event.get_profiling_info<sycl::info::event_profiling::command_end>();
220 return (end - start);
223 bool hasPendingWork()
final
230 sycl::event m_sycl_event;
240 friend class SyclRunQueueStream;
244 void notifyBeginLaunchKernel()
override
247 void notifyEndLaunchKernel()
override
250 void barrier()
override
254 m_default_queue->wait();
262 return new SyclRunQueueStream(
this, bi);
273 [[maybe_unused]]
DeviceId device_id)
override
281 void setCurrentDevice([[maybe_unused]]
DeviceId device_id)
final
283 ARCANE_SYCL_FUNC_NOT_HANDLED;
285 const IDeviceInfoList* deviceInfoList()
override {
return &m_device_info_list; }
287 void getPointerAttribute(
PointerAttribute& attribute,
const void* ptr)
override
289 sycl::usm::alloc sycl_mem_type = sycl::get_pointer_type(ptr, *m_default_context);
291 const void* host_ptr =
nullptr;
292 const void* device_ptr =
nullptr;
293 if (sycl_mem_type == sycl::usm::alloc::host) {
296 mem_type = ePointerMemoryType::Host;
301 else if (sycl_mem_type == sycl::usm::alloc::device) {
302 mem_type = ePointerMemoryType::Device;
305 else if (sycl_mem_type == sycl::usm::alloc::shared) {
306 mem_type = ePointerMemoryType::Managed;
314 _fillPointerAttribute(attribute, mem_type, device_id, ptr, device_ptr, host_ptr);
322 void fillDevicesAndSetDefaultQueue(
bool is_verbose);
323 sycl::queue& defaultQueue()
const {
return *m_default_queue; }
324 sycl::device& defaultDevice()
const {
return *m_default_device; }
329 std::unique_ptr<sycl::device> m_default_device;
330 std::unique_ptr<sycl::context> m_default_context;
331 std::unique_ptr<sycl::queue> m_default_queue;
335 void _init(sycl::device& device)
337 m_default_device = std::make_unique<sycl::device>(device);
338 m_default_queue = std::make_unique<sycl::queue>(device);
339 m_default_context = std::make_unique<sycl::context>(device);
350 sycl::device& d = runtime->defaultDevice();
353 auto queue_property = sycl::property::queue::in_order();
355 auto profiling_property = sycl::property::queue::enable_profiling();
356 sycl::property_list queue_properties(queue_property, profiling_property);
359 sycl::async_handler err_handler;
360 err_handler = _getAsyncHandler();
362 m_sycl_stream = std::make_unique<sycl::queue>(d, err_handler, queue_properties);
364 ARCANE_SYCL_FUNC_NOT_HANDLED;
365 m_sycl_stream = std::make_unique<sycl::queue>(d, err_handler, queue_properties);
372void SyclRunnerRuntime::
373fillDevicesAndSetDefaultQueue(
bool is_verbose)
376 for (
auto platform : sycl::platform::get_platforms()) {
377 std::cout <<
"Platform: "
378 <<
platform.get_info<sycl::info::platform::name>()
383 sycl::device device{ sycl::gpu_selector_v };
385 std::cout <<
"\nDevice: " << device.get_info<sycl::info::device::name>()
386 <<
"\nVersion=" << device.get_info<sycl::info::device::version>()
392 DeviceInfo device_info;
393 device_info.setDescription(
"No description info");
394 device_info.setDeviceId(DeviceId(0));
395 device_info.setName(device.get_info<sycl::info::device::name>());
396 m_device_info_list.addDevice(device_info);
424namespace Arcane::Accelerator::Sycl
430void SyclMemoryCopier::
439 sycl::queue& q = global_sycl_runtime.defaultQueue();
450extern "C" ARCANE_EXPORT
void
454 using namespace Arcane::Accelerator::Sycl;
455 Arcane::Accelerator::impl::setUsingSYCLRuntime(
true);
456 Arcane::Accelerator::impl::setSYCLRunQueueRuntime(&global_sycl_runtime);
464 mrm->
setCopier(&global_sycl_memory_copier);
465 global_sycl_runtime.fillDevicesAndSetDefaultQueue(init_info.isVerbose());
466 setSyclMemoryQueue(global_sycl_runtime.defaultQueue());
#define ARCANE_CHECK_POINTER(ptr)
Macro retournant le pointeur ptr s'il est non nul ou lancant une exception s'il est nul.
#define ARCANE_THROW(exception_class,...)
Macro pour envoyer une exception avec formattage.
#define ARCANE_FATAL(...)
Macro envoyant une exception FatalErrorException.
Identifiant d'un composant du système.
Information mémoire d'un accélérateur.
Interface d'une liste de devices.
Arguments pour la copie mémoire.
Arguments pour le préfetching mémoire.
Informations sur une adresse mémoire.
Informations pour initialiser le runtime accélérateur.
Informations pour créer une RunQueue.
bool isDefault() const
Indique si l'instance a uniquement les valeurs par défaut.
File d'exécution pour un accélérateur.
bool isAsync() const
Indique si la file d'exécution est asynchrone.
void copyMemory(const MemoryCopyArgs &args) const
Copie des informations entre deux zones mémoires.
void copy(ConstMemoryView from, eMemoryRessource from_mem, MutableMemoryView to, eMemoryRessource to_mem, const RunQueue *queue) override
Copie les données de from vers to avec la queue queue.
impl::NativeStream nativeStream() override
Pointeur sur la structure interne dépendante de l'implémentation.
void barrier() override
Bloque jusqu'à ce que toutes les actions associées à cette file soient terminées.
sycl::event lastCommandEvent()
Évènement correspondant à la dernière commande.
void prefetchMemory(const MemoryPrefetchArgs &args) override
Effectue un pré-chargement d'une zone mémoire.
void copyMemory(const MemoryCopyArgs &args) override
Effectue une copie entre deux zones mémoire.
bool _barrierNoException() override
Barrière sans exception. Retourne true en cas d'erreur.
void _setSyclLastCommandEvent(void *sycl_event_ptr) override
Pour SYCL, positionne l'évènement associé à la dernière commande exécutée.
void notifyEndLaunchKernel(impl::RunCommandImpl &) override
Notification de fin de lancement de la commande.
void notifyBeginLaunchKernel(impl::RunCommandImpl &c) override
Notification avant le lancement de la commande.
Interface d'une liste de devices.
Interface de l'implémentation d'un évènement.
Interface d'un flux d'exécution pour une RunQueue.
Interface du runtime associé à un accélérateur.
Type opaque pour encapsuler une 'stream' native.
Implémentation d'une commande pour accélérateur.
Vue constante sur une zone mémoire contigue contenant des éléments de taille fixe.
constexpr SpanType bytes() const
Vue sous forme d'octets.
constexpr const std::byte * data() const
Pointeur sur la zone mémoire.
Interface pour les copies mémoire avec support des accélérateurs.
Partie interne à Arcane de 'IMemoryRessourceMng'.
virtual void setAllocator(eMemoryResource r, IMemoryAllocator *allocator)=0
Positionne l'allocateur pour la ressource r.
virtual void setIsAccelerator(bool v)=0
Indique si un accélérateur est disponible.
virtual void setCopier(IMemoryCopier *copier)=0
Positionne l'instance gérant les copies.
virtual IMemoryResourceMngInternal * _internal()=0
Interface interne.
Vue modifiable sur une zone mémoire contigue contenant des éléments de taille fixe.
constexpr std::byte * data() const
Pointeur sur la zone mémoire.
constexpr SpanType bytes() const
Vue sous forme d'octets.
Exception lorsqu'une fonction n'est pas implémentée.
Exception lorsqu'une opération n'est pas supportée.
constexpr __host__ __device__ SizeType size() const noexcept
Retourne la taille du tableau.
eMemoryAdvice
Conseils pour la gestion mémoire.
ePointerMemoryType
Type de mémoire pour un pointeur.
eExecutionPolicy
Politique d'exécution pour un Runner.
@ SYCL
Politique d'exécution utilisant l'environnement SYCL.
IMemoryRessourceMng * getDataMemoryResourceMng()
Gestionnaire de ressource mémoire pour les données.
IMemoryAllocator * setAcceleratorHostMemoryAllocator(IMemoryAllocator *a)
Positionne l'allocateur spécifique pour les accélérateurs.
void setDefaultDataMemoryResource(eMemoryResource mem_resource)
Positionne la ressource mémoire utilisée pour l'allocateur mémoire des données.
-*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
@ HostPinned
Alloue sur l'hôte.
@ UnifiedMemory
Alloue en utilisant la mémoire unifiée.
@ Device
Alloue sur le device.
Arcane::eMemoryResource eMemoryRessource
Typedef pour la version Arcane historique (avec 2's')