Skip to content

Commit dc12589

Browse files
Neo ZhangNeo Zhang
authored andcommitted
add dev2dev memcpy by SYCL API
1 parent db94854 commit dc12589

4 files changed

Lines changed: 60 additions & 21 deletions

File tree

docs/backend/SYCL.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -727,6 +727,7 @@ Pass these via `CXXFLAGS` or add a one-off `#define` to enable a flag on the spo
727727
|-----------------|----------------------------------------------------------------------------------|
728728
| DEBUG_SYCL_POOL | Enable device memory pool logging on teardown. Useful for profiling allocations. |
729729
| DEBUG_SYCL_MALLOC | Enable verbose per-call logging of device pool alloc/free operations. |
730+
| GGML_SYCL_DEV2DEV_MEMCPY | Choose the SYCL or L0 API in dev2dev memory copy.<br>Value: <br>* 0: SYCL API (default)<br>* 1: L0 API -- L0 API is found to lead to abnormal crash in some case. This debug flag is used to check the issue.|
730731

731732
## Design Rule
732733

ggml/src/ggml-sycl/common.hpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ extern int g_ggml_sycl_debug;
6262
extern int g_ggml_sycl_disable_optimize;
6363
extern int g_ggml_sycl_prioritize_dmmv;
6464
extern int g_ggml_sycl_enable_flash_attention;
65+
extern int g_ggml_sycl_dev2dev_memcpy;
6566

6667

6768
#if defined(__clang__) && __has_builtin(__builtin_expect)
@@ -126,6 +127,11 @@ enum ggml_sycl_backend_gpu_mode {
126127
SYCL_MUL_GPU_MODE
127128
};
128129

130+
enum ggml_sycl_dev2dev_memcpy_mode {
131+
DEV2DEV_MEMCPY_SYCL = 0,
132+
DEV2DEV_MEMCPY_L0 = 1,
133+
};
134+
129135
static_assert(sizeof(sycl::half) == sizeof(ggml_fp16_t), "wrong fp16 size");
130136

131137
static void crash() {

ggml/src/ggml-sycl/dpct/helper.hpp

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,14 @@
1313
#ifndef GGML_SYCL_DPCT_HELPER_HPP
1414
#define GGML_SYCL_DPCT_HELPER_HPP
1515

16+
#include <cstdlib>
17+
#include <iostream>
18+
#include <map>
19+
1620
#include <sycl/sycl.hpp>
1721
#include <sycl/half_type.hpp>
1822
#include <oneapi/mkl.hpp>
1923

20-
#include <map>
21-
22-
#include "ggml.h"
23-
2424
#if defined(__linux__)
2525
#include <sys/mman.h>
2626
#elif defined(_WIN64)
@@ -43,6 +43,7 @@
4343
#include <windows.h>
4444
#endif
4545

46+
4647
#define DPCT_COMPATIBILITY_TEMP (900)
4748

4849
#if defined(_MSC_VER)
@@ -59,6 +60,13 @@
5960
#define __dpct_noinline__ __attribute__((noinline))
6061
#endif
6162

63+
#define DPCT_UNUSED(x) (void)(x)
64+
65+
inline void _abort(char * str) {
66+
std::cerr << str << std::endl;
67+
std::abort();
68+
}
69+
6270
inline std::string get_device_type_name(const sycl::device &Device) {
6371
auto DeviceType = Device.get_info<sycl::info::device::device_type>();
6472
switch (DeviceType) {
@@ -1017,7 +1025,7 @@ namespace dpct
10171025
if (backend == "opencl:cpu") return 4;
10181026
if (backend == "opencl:acc") return 5;
10191027
printf("convert_backend_index: can't handle backend=%s\n", backend.c_str());
1020-
GGML_ABORT("fatal error");
1028+
_abort("fatal error");
10211029
}
10221030
static bool compare_backend(std::string &backend1, std::string &backend2) {
10231031
return convert_backend_index(backend1) < convert_backend_index(backend2);
@@ -1426,7 +1434,7 @@ namespace dpct
14261434
if (!size)
14271435
return sycl::event{};
14281436
return q.memcpy(to_ptr, from_ptr, size, dep_events);
1429-
GGML_UNUSED(direction);
1437+
DPCT_UNUSED(direction);
14301438
}
14311439

14321440
// Get actual copy range and make sure it will not exceed range.
@@ -2092,7 +2100,7 @@ namespace dpct
20922100
if (!size)
20932101
return sycl::event{};
20942102
return q.memcpy(to_ptr, from_ptr, size, dep_events);
2095-
GGML_UNUSED(direction);
2103+
DPCT_UNUSED(direction);
20962104
}
20972105

20982106
// Get actual copy range and make sure it will not exceed range.

ggml/src/ggml-sycl/ggml-sycl.cpp

Lines changed: 38 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ int g_ggml_sycl_use_async_mem_op = 0;
8282
int g_ggml_sycl_use_async_mem_op_requested = 1;
8383
int g_ggml_sycl_enable_level_zero = 0;
8484
int g_ggml_sycl_enable_flash_attention = 1;
85+
int g_ggml_sycl_dev2dev_memcpy = DEV2DEV_MEMCPY_SYCL;
8586

8687

8788
static ggml_sycl_device_info ggml_sycl_init() {
@@ -266,6 +267,11 @@ static void ggml_check_sycl() try {
266267
g_ggml_sycl_enable_level_zero = 0;
267268
#endif
268269

270+
g_ggml_sycl_dev2dev_memcpy = get_sycl_env("GGML_SYCL_DEV2DEV_MEMCPY", DEV2DEV_MEMCPY_SYCL);
271+
if (g_ggml_sycl_enable_level_zero == 0) {
272+
g_ggml_sycl_dev2dev_memcpy = DEV2DEV_MEMCPY_SYCL;
273+
}
274+
269275
#ifdef SYCL_FLASH_ATTN
270276
g_ggml_sycl_enable_flash_attention = get_sycl_env("GGML_SYCL_ENABLE_FLASH_ATTN", 1);
271277
#else
@@ -316,8 +322,11 @@ static void ggml_check_sycl() try {
316322
#endif
317323
#ifdef GGML_SYCL_SUPPORT_LEVEL_ZERO
318324
GGML_LOG_INFO(" GGML_SYCL_ENABLE_LEVEL_ZERO: %d\n", g_ggml_sycl_enable_level_zero);
325+
GGML_LOG_INFO(" GGML_SYCL_DEV2DEV_MEMCPY: %d\n", g_ggml_sycl_dev2dev_memcpy);
319326
#else
320327
GGML_LOG_INFO(" GGML_SYCL_ENABLE_LEVEL_ZERO: Level Zero disabled by compile flag\n");
328+
GGML_LOG_INFO(" GGML_SYCL_DEV2DEV_MEMCPY: %d, enable to SYCL API since missing GGML_SYCL_SUPPORT_LEVEL_ZERO\n",
329+
g_ggml_sycl_dev2dev_memcpy);
321330
#endif
322331
#if GGML_SYCL_DNNL
323332
GGML_LOG_INFO(" GGML_SYCL_DISABLE_DNN: %d\n", g_ggml_sycl_disable_dnn);
@@ -584,27 +593,42 @@ static bool ggml_sycl_is_l0_discrete_gpu(sycl::queue &q) {
584593

585594
static void dev2dev_memcpy(sycl::queue &q_dst, sycl::queue &q_src, void *ptr_dst,
586595
const void *ptr_src, size_t size) {
596+
587597
#ifdef GGML_SYCL_SUPPORT_LEVEL_ZERO
588-
// Use Level Zero direct copy for dGPU-to-dGPU transfers.
589-
const bool l0_copy_supported =
590-
ggml_sycl_is_l0_discrete_gpu(q_dst) && ggml_sycl_is_l0_discrete_gpu(q_src);
591-
if (g_ggml_sycl_enable_level_zero && l0_copy_supported) {
592-
auto ze_ctx = sycl::get_native<sycl::backend::ext_oneapi_level_zero>(q_dst.get_context());
593-
auto ze_dev = sycl::get_native<sycl::backend::ext_oneapi_level_zero>(q_dst.get_device());
594-
ze_command_queue_desc_t cq_desc = {ZE_STRUCTURE_TYPE_COMMAND_QUEUE_DESC, nullptr, 0, 0,
595-
0, ZE_COMMAND_QUEUE_MODE_SYNCHRONOUS, ZE_COMMAND_QUEUE_PRIORITY_NORMAL};
596-
ze_command_list_handle_t cl;
597-
ze_result_t r = zeCommandListCreateImmediate(ze_ctx, ze_dev, &cq_desc, &cl);
598-
if (r == ZE_RESULT_SUCCESS) {
599-
r = zeCommandListAppendMemoryCopy(cl, ptr_dst, ptr_src, size, nullptr, 0, nullptr);
600-
zeCommandListDestroy(cl);
598+
if (g_ggml_sycl_dev2dev_memcpy == DEV2DEV_MEMCPY_L0) {
599+
// Use Level Zero direct copy for dGPU-to-dGPU transfers.
600+
const bool l0_copy_supported =
601+
ggml_sycl_is_l0_discrete_gpu(q_dst) && ggml_sycl_is_l0_discrete_gpu(q_src);
602+
if (g_ggml_sycl_enable_level_zero && l0_copy_supported) {
603+
604+
auto ze_ctx = sycl::get_native<sycl::backend::ext_oneapi_level_zero>(q_dst.get_context());
605+
auto ze_dev = sycl::get_native<sycl::backend::ext_oneapi_level_zero>(q_dst.get_device());
606+
ze_command_queue_desc_t cq_desc = {ZE_STRUCTURE_TYPE_COMMAND_QUEUE_DESC, nullptr, 0, 0,
607+
0, ZE_COMMAND_QUEUE_MODE_SYNCHRONOUS, ZE_COMMAND_QUEUE_PRIORITY_NORMAL};
608+
ze_command_list_handle_t cl;
609+
ze_result_t r = zeCommandListCreateImmediate(ze_ctx, ze_dev, &cq_desc, &cl);
601610
if (r == ZE_RESULT_SUCCESS) {
602-
return;
611+
GGML_SYCL_DEBUG("[SYCL] dev2dev memcpy by L0\n");
612+
r = zeCommandListAppendMemoryCopy(cl, ptr_dst, ptr_src, size, nullptr, 0, nullptr);
613+
zeCommandListDestroy(cl);
614+
if (r == ZE_RESULT_SUCCESS) {
615+
return;
616+
}
603617
}
604618
}
605619
}
606620
#endif
621+
622+
if (g_ggml_sycl_dev2dev_memcpy == DEV2DEV_MEMCPY_SYCL) {
623+
if (q_dst.get_device().get_platform() == q_src.get_device().get_platform()){
624+
GGML_SYCL_DEBUG("[SYCL] dev2dev memcpy by SYCL\n");
625+
SYCL_CHECK(CHECK_TRY_ERROR(q_dst.memcpy(ptr_dst, ptr_src, size).wait()));
626+
return;
627+
}
628+
}
629+
607630
// Host-staged copy
631+
GGML_SYCL_DEBUG("[SYCL] dev2dev memcpy by host forward\n");
608632
char *host_buf = (char *)malloc(size);
609633
q_src.memcpy(host_buf, (const char *)ptr_src, size).wait();
610634
q_dst.memcpy((char *)ptr_dst, host_buf, size).wait();

0 commit comments

Comments
 (0)