0011-add-unpad-operator.patch 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409
  1. From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
  2. From: Michael Yang <mxyng@pm.me>
  3. Date: Thu, 17 Oct 2024 17:19:25 -0700
  4. Subject: [PATCH] add unpad operator
  5. ---
  6. ggml/include/ggml.h | 10 ++++
  7. ggml/src/ggml-cuda.cu | 4 ++
  8. ggml/src/ggml-cuda/pad.cu | 46 +++++++++++++++++++
  9. ggml/src/ggml-cuda/pad.cuh | 1 +
  10. ggml/src/ggml-metal.m | 33 ++++++++++++++
  11. ggml/src/ggml-metal.metal | 45 ++++++++++++++++++
  12. ggml/src/ggml.c | 93 +++++++++++++++++++++++++++++++++++++-
  13. 7 files changed, 230 insertions(+), 2 deletions(-)
  14. diff --git a/ggml/include/ggml.h b/ggml/include/ggml.h
  15. index ce3d92cb..962cb5f7 100644
  16. --- a/ggml/include/ggml.h
  17. +++ b/ggml/include/ggml.h
  18. @@ -506,6 +506,7 @@ extern "C" {
  19. GGML_OP_POOL_2D_BACK,
  20. GGML_OP_UPSCALE, // nearest interpolate
  21. GGML_OP_PAD,
  22. + GGML_OP_UNPAD,
  23. GGML_OP_ARANGE,
  24. GGML_OP_TIMESTEP_EMBEDDING,
  25. GGML_OP_ARGSORT,
  26. @@ -1764,6 +1765,15 @@ extern "C" {
  27. int p2,
  28. int p3);
  29. + // unpad each dimension: [x, ..., x, y, ..., y] -> [x, ..., x]
  30. + GGML_API struct ggml_tensor * ggml_unpad(
  31. + struct ggml_context * ctx,
  32. + struct ggml_tensor * a,
  33. + int p0,
  34. + int p1,
  35. + int p2,
  36. + int p3);
  37. +
  38. // Ref: https://github.com/CompVis/stable-diffusion/blob/main/ldm/modules/diffusionmodules/util.py#L151
  39. // timesteps: [N,]
  40. // return: [N, dim]
  41. diff --git a/ggml/src/ggml-cuda.cu b/ggml/src/ggml-cuda.cu
  42. index fe77b81c..6e84af56 100644
  43. --- a/ggml/src/ggml-cuda.cu
  44. +++ b/ggml/src/ggml-cuda.cu
  45. @@ -2270,6 +2270,9 @@ static bool ggml_cuda_compute_forward(ggml_backend_cuda_context & ctx, struct gg
  46. case GGML_OP_PAD:
  47. ggml_cuda_op_pad(ctx, dst);
  48. break;
  49. + case GGML_OP_UNPAD:
  50. + ggml_cuda_op_unpad(ctx, dst);
  51. + break;
  52. case GGML_OP_ARANGE:
  53. ggml_cuda_op_arange(ctx, dst);
  54. break;
  55. @@ -2992,6 +2995,7 @@ GGML_CALL static bool ggml_backend_cuda_supports_op(ggml_backend_t backend, cons
  56. case GGML_OP_GROUP_NORM:
  57. case GGML_OP_UPSCALE:
  58. case GGML_OP_PAD:
  59. + case GGML_OP_UNPAD:
  60. case GGML_OP_ARANGE:
  61. case GGML_OP_TIMESTEP_EMBEDDING:
  62. case GGML_OP_LEAKY_RELU:
  63. diff --git a/ggml/src/ggml-cuda/pad.cu b/ggml/src/ggml-cuda/pad.cu
  64. index aba539e8..39fd4b16 100644
  65. --- a/ggml/src/ggml-cuda/pad.cu
  66. +++ b/ggml/src/ggml-cuda/pad.cu
  67. @@ -47,3 +47,49 @@ void ggml_cuda_op_pad(ggml_backend_cuda_context & ctx, ggml_tensor * dst) {
  68. src0->ne[0], src0->ne[1], src0->ne[2], src0->ne[3],
  69. dst->ne[0], dst->ne[1], dst->ne[2], dst->ne[3], stream);
  70. }
  71. +
  72. +static __global__ void unpad_f32(const float * x, float * dst, const int ne0, const int ne00, const int ne01, const int ne02, const int ne03) {
  73. + // blockIdx.z: idx of ne2*ne3, aka ne02*ne03
  74. + // blockIdx.y: idx of ne1
  75. + // blockIDx.x: idx of ne0 / BLOCK_SIZE
  76. + int nidx = threadIdx.x + blockIdx.x * blockDim.x;
  77. + if (nidx >= ne0) {
  78. + return;
  79. + }
  80. +
  81. + // operation
  82. + int offset_dst =
  83. + nidx +
  84. + blockIdx.y * ne0 +
  85. + blockIdx.z * ne0 * gridDim.y;
  86. + if (nidx < ne00 && blockIdx.y < ne01 && blockIdx.z < ne02*ne03) {
  87. + int offset_src =
  88. + nidx +
  89. + blockIdx.y * ne00 +
  90. + blockIdx.z * ne00 * ne01;
  91. + dst[offset_dst] = x[offset_src];
  92. + }
  93. +}
  94. +
  95. +static void unpad_f32_cuda(const float * x, float * dst,
  96. + const int ne00, const int ne01, const int ne02, const int ne03,
  97. + const int ne0, const int ne1, const int ne2, const int ne3, cudaStream_t stream) {
  98. + int num_blocks = (ne0 + CUDA_PAD_BLOCK_SIZE - 1) / CUDA_PAD_BLOCK_SIZE;
  99. + dim3 gridDim(num_blocks, ne1, ne2*ne3);
  100. + unpad_f32<<<gridDim, CUDA_PAD_BLOCK_SIZE, 0, stream>>>(x, dst, ne0, ne00, ne01, ne02, ne03);
  101. +}
  102. +
  103. +void ggml_cuda_op_unpad(ggml_backend_cuda_context & ctx, ggml_tensor * dst) {
  104. + const ggml_tensor * src0 = dst->src[0];
  105. + const float * src0_d = (const float *)src0->data;
  106. + float * dst_d = (float *)dst->data;
  107. + cudaStream_t stream = ctx.stream();
  108. +
  109. + GGML_ASSERT(src0->type == GGML_TYPE_F32);
  110. + GGML_ASSERT(dst->type == GGML_TYPE_F32);
  111. + GGML_ASSERT(src0->ne[3] == 1 && dst->ne[3] == 1); // just 3D tensors
  112. +
  113. + unpad_f32_cuda(src0_d, dst_d,
  114. + src0->ne[0], src0->ne[1], src0->ne[2], src0->ne[3],
  115. + dst->ne[0], dst->ne[1], dst->ne[2], dst->ne[3], stream);
  116. +}
  117. diff --git a/ggml/src/ggml-cuda/pad.cuh b/ggml/src/ggml-cuda/pad.cuh
  118. index 8fd386b0..e2ededc3 100644
  119. --- a/ggml/src/ggml-cuda/pad.cuh
  120. +++ b/ggml/src/ggml-cuda/pad.cuh
  121. @@ -3,3 +3,4 @@
  122. #define CUDA_PAD_BLOCK_SIZE 256
  123. void ggml_cuda_op_pad(ggml_backend_cuda_context & ctx, ggml_tensor * dst);
  124. +void ggml_cuda_op_unpad(ggml_backend_cuda_context & ctx, ggml_tensor * dst);
  125. diff --git a/ggml/src/ggml-metal.m b/ggml/src/ggml-metal.m
  126. index 829c5e39..25702d85 100644
  127. --- a/ggml/src/ggml-metal.m
  128. +++ b/ggml/src/ggml-metal.m
  129. @@ -193,6 +193,7 @@
  130. GGML_METAL_KERNEL_TYPE_IM2COL_F32,
  131. GGML_METAL_KERNEL_TYPE_UPSCALE_F32,
  132. GGML_METAL_KERNEL_TYPE_PAD_F32,
  133. + GGML_METAL_KERNEL_TYPE_UNPAD_F32,
  134. GGML_METAL_KERNEL_TYPE_ARANGE_F32,
  135. GGML_METAL_KERNEL_TYPE_TIMESTEP_EMBEDDING_F32,
  136. GGML_METAL_KERNEL_TYPE_ARGSORT_F32_I32_ASC,
  137. @@ -689,6 +690,7 @@ static void ggml_metal_log(enum ggml_log_level level, const char * format, ...){
  138. GGML_METAL_ADD_KERNEL(GGML_METAL_KERNEL_TYPE_IM2COL_F32, im2col_f32, true);
  139. GGML_METAL_ADD_KERNEL(GGML_METAL_KERNEL_TYPE_UPSCALE_F32, upscale_f32, true);
  140. GGML_METAL_ADD_KERNEL(GGML_METAL_KERNEL_TYPE_PAD_F32, pad_f32, true);
  141. + GGML_METAL_ADD_KERNEL(GGML_METAL_KERNEL_TYPE_UNPAD_F32, unpad_f32, true);
  142. GGML_METAL_ADD_KERNEL(GGML_METAL_KERNEL_TYPE_TIMESTEP_EMBEDDING_F32, timestep_embedding_f32, true);
  143. GGML_METAL_ADD_KERNEL(GGML_METAL_KERNEL_TYPE_ARANGE_F32, arange_f32, true);
  144. GGML_METAL_ADD_KERNEL(GGML_METAL_KERNEL_TYPE_ARGSORT_F32_I32_ASC, argsort_f32_i32_asc, true);
  145. @@ -846,6 +848,7 @@ static bool ggml_metal_supports_op(const struct ggml_backend_metal_context * ctx
  146. return false;
  147. case GGML_OP_UPSCALE:
  148. case GGML_OP_PAD:
  149. + case GGML_OP_UNPAD:
  150. case GGML_OP_ARANGE:
  151. case GGML_OP_TIMESTEP_EMBEDDING:
  152. case GGML_OP_ARGSORT:
  153. @@ -2655,6 +2658,36 @@ static void ggml_metal_encode_node(
  154. const int nth = MIN(1024, ne0);
  155. + [encoder dispatchThreadgroups:MTLSizeMake(ne1, ne2, ne3) threadsPerThreadgroup:MTLSizeMake(nth, 1, 1)];
  156. + } break;
  157. + case GGML_OP_UNPAD:
  158. + {
  159. + GGML_ASSERT(src0->type == GGML_TYPE_F32);
  160. +
  161. + id<MTLComputePipelineState> pipeline = ctx->kernels[GGML_METAL_KERNEL_TYPE_UNPAD_F32].pipeline;
  162. +
  163. + [encoder setComputePipelineState:pipeline];
  164. + [encoder setBuffer:id_src0 offset:offs_src0 atIndex:0];
  165. + [encoder setBuffer:id_dst offset:offs_dst atIndex:1];
  166. + [encoder setBytes:&ne00 length:sizeof(ne00) atIndex:2];
  167. + [encoder setBytes:&ne01 length:sizeof(ne01) atIndex:3];
  168. + [encoder setBytes:&ne02 length:sizeof(ne02) atIndex:4];
  169. + [encoder setBytes:&ne03 length:sizeof(ne03) atIndex:5];
  170. + [encoder setBytes:&nb00 length:sizeof(nb00) atIndex:6];
  171. + [encoder setBytes:&nb01 length:sizeof(nb01) atIndex:7];
  172. + [encoder setBytes:&nb02 length:sizeof(nb02) atIndex:8];
  173. + [encoder setBytes:&nb03 length:sizeof(nb03) atIndex:9];
  174. + [encoder setBytes:&ne0 length:sizeof(ne0) atIndex:10];
  175. + [encoder setBytes:&ne1 length:sizeof(ne1) atIndex:11];
  176. + [encoder setBytes:&ne2 length:sizeof(ne2) atIndex:12];
  177. + [encoder setBytes:&ne3 length:sizeof(ne3) atIndex:13];
  178. + [encoder setBytes:&nb0 length:sizeof(nb0) atIndex:14];
  179. + [encoder setBytes:&nb1 length:sizeof(nb1) atIndex:15];
  180. + [encoder setBytes:&nb2 length:sizeof(nb2) atIndex:16];
  181. + [encoder setBytes:&nb3 length:sizeof(nb3) atIndex:17];
  182. +
  183. + const int nth = MIN(1024, ne0);
  184. +
  185. [encoder dispatchThreadgroups:MTLSizeMake(ne1, ne2, ne3) threadsPerThreadgroup:MTLSizeMake(nth, 1, 1)];
  186. } break;
  187. case GGML_OP_ARANGE:
  188. diff --git a/ggml/src/ggml-metal.metal b/ggml/src/ggml-metal.metal
  189. index 2b200032..09887511 100644
  190. --- a/ggml/src/ggml-metal.metal
  191. +++ b/ggml/src/ggml-metal.metal
  192. @@ -2029,6 +2029,51 @@ kernel void kernel_pad_f32(
  193. }
  194. }
  195. +kernel void kernel_unpad_f32(
  196. + device const char * src0,
  197. + device char * dst,
  198. + constant int64_t & ne00,
  199. + constant int64_t & ne01,
  200. + constant int64_t & ne02,
  201. + constant int64_t & ne03,
  202. + constant uint64_t & nb00,
  203. + constant uint64_t & nb01,
  204. + constant uint64_t & nb02,
  205. + constant uint64_t & nb03,
  206. + constant int64_t & ne0,
  207. + constant int64_t & ne1,
  208. + constant int64_t & ne2,
  209. + constant int64_t & ne3,
  210. + constant uint64_t & nb0,
  211. + constant uint64_t & nb1,
  212. + constant uint64_t & nb2,
  213. + constant uint64_t & nb3,
  214. + uint3 tgpig[[threadgroup_position_in_grid]],
  215. + uint3 tpitg[[thread_position_in_threadgroup]],
  216. + uint3 ntg[[threads_per_threadgroup]]) {
  217. +
  218. + const int64_t i3 = tgpig.z;
  219. + const int64_t i2 = tgpig.y;
  220. + const int64_t i1 = tgpig.x;
  221. +
  222. + const int64_t i03 = i3;
  223. + const int64_t i02 = i2;
  224. + const int64_t i01 = i1;
  225. +
  226. + device const float * src0_ptr = (device const float *) (src0 + i03*nb03 + i02*nb02 + i01*nb01);
  227. + device float * dst_ptr = (device float *) (dst + i3*nb3 + i2*nb2 + i1*nb1);
  228. +
  229. + if (i1 < ne01 && i2 < ne02 && i3 < ne03) {
  230. + for (int i0 = tpitg.x; i0 < ne0; i0 += ntg.x) {
  231. + if (i0 < ne00) {
  232. + dst_ptr[i0] = src0_ptr[i0];
  233. + }
  234. + }
  235. +
  236. + return;
  237. + }
  238. +}
  239. +
  240. kernel void kernel_arange_f32(
  241. device char * dst,
  242. constant int64_t & ne0,
  243. diff --git a/ggml/src/ggml.c b/ggml/src/ggml.c
  244. index bcbc32d9..f4864ac8 100644
  245. --- a/ggml/src/ggml.c
  246. +++ b/ggml/src/ggml.c
  247. @@ -2997,6 +2997,7 @@ static const char * GGML_OP_NAME[GGML_OP_COUNT] = {
  248. "POOL_2D_BACK",
  249. "UPSCALE",
  250. "PAD",
  251. + "UNPAD",
  252. "ARANGE",
  253. "TIMESTEP_EMBEDDING",
  254. "ARGSORT",
  255. @@ -3030,7 +3031,7 @@ static const char * GGML_OP_NAME[GGML_OP_COUNT] = {
  256. "OPT_STEP_ADAMW",
  257. };
  258. -static_assert(GGML_OP_COUNT == 80, "GGML_OP_COUNT != 80");
  259. +static_assert(GGML_OP_COUNT == 81, "GGML_OP_COUNT != 81");
  260. static const char * GGML_OP_SYMBOL[GGML_OP_COUNT] = {
  261. "none",
  262. @@ -3091,6 +3092,7 @@ static const char * GGML_OP_SYMBOL[GGML_OP_COUNT] = {
  263. "pool_2d_back(x)",
  264. "upscale(x)",
  265. "pad(x)",
  266. + "unpad(x)",
  267. "arange(start, stop, step)",
  268. "timestep_embedding(timesteps, dim, max_period)",
  269. "argsort(x)",
  270. @@ -3124,7 +3126,7 @@ static const char * GGML_OP_SYMBOL[GGML_OP_COUNT] = {
  271. "adamw(x)",
  272. };
  273. -static_assert(GGML_OP_COUNT == 80, "GGML_OP_COUNT != 80");
  274. +static_assert(GGML_OP_COUNT == 81, "GGML_OP_COUNT != 81");
  275. static_assert(GGML_OP_POOL_COUNT == 2, "GGML_OP_POOL_COUNT != 2");
  276. @@ -6955,6 +6957,32 @@ struct ggml_tensor * ggml_pad(
  277. return result;
  278. }
  279. +// ggml_unpad
  280. +
  281. +struct ggml_tensor * ggml_unpad(
  282. + struct ggml_context * ctx,
  283. + struct ggml_tensor * a,
  284. + int p0, int p1, int p2, int p3) {
  285. + bool is_node = false;
  286. +
  287. + if (a->grad) {
  288. + GGML_ABORT("fatal error"); // TODO: implement backward
  289. + is_node = true;
  290. + }
  291. +
  292. + struct ggml_tensor * result = ggml_new_tensor_4d(ctx, a->type,
  293. + a->ne[0] - p0,
  294. + a->ne[1] - p1,
  295. + a->ne[2] - p2,
  296. + a->ne[3] - p3);
  297. +
  298. + result->op = GGML_OP_UNPAD;
  299. + result->grad = is_node ? ggml_dup_tensor(ctx, result) : NULL;
  300. + result->src[0] = a;
  301. +
  302. + return result;
  303. +}
  304. +
  305. // ggml_arange
  306. struct ggml_tensor * ggml_arange(
  307. @@ -15312,6 +15340,58 @@ static void ggml_compute_forward_pad(
  308. }
  309. }
  310. +static void ggml_compute_forward_unpad_f32(
  311. + const struct ggml_compute_params *params,
  312. + struct ggml_tensor *dst) {
  313. +
  314. + const struct ggml_tensor * src0 = dst->src[0];
  315. +
  316. + GGML_ASSERT(src0->nb[0] == sizeof(float));
  317. + GGML_ASSERT( dst->nb[0] == sizeof(float));
  318. +
  319. + const int ith = params->ith;
  320. + const int nth = params->nth;
  321. +
  322. + GGML_TENSOR_UNARY_OP_LOCALS
  323. +
  324. + float * dst_ptr = (float *) dst->data;
  325. +
  326. + // TODO: optimize
  327. +
  328. + for (int64_t i2 = 0; i2 < ne2; ++i2) {
  329. + for (int64_t i1 = ith; i1 < ne1; i1 += nth) {
  330. + for (int64_t i0 = 0; i0 < ne0; ++i0) {
  331. + for (int64_t i3 = 0; i3 < ne3; ++i3) {
  332. + const int64_t dst_idx = i3*(ne0*ne1*ne2) + i2*(ne0*ne1) + i1*ne0 + i0;
  333. +
  334. + const float * src_ptr = (const float *)((char *) src0->data + i3*nb03 + i2*nb02 + i1*nb01 + i0*nb00);
  335. +
  336. + if (i0 < ne00 && i1 < ne01 && i2 < ne02 && i3 < ne03) {
  337. + dst_ptr[dst_idx] = *src_ptr;
  338. + }
  339. + }
  340. + }
  341. + }
  342. + }
  343. +}
  344. +
  345. +static void ggml_compute_forward_unpad(
  346. + const struct ggml_compute_params * params,
  347. + struct ggml_tensor * dst) {
  348. +
  349. + const struct ggml_tensor * src0 = dst->src[0];
  350. +
  351. + switch (src0->type) {
  352. + case GGML_TYPE_F32:
  353. + {
  354. + ggml_compute_forward_unpad_f32(params, dst);
  355. + } break;
  356. + default:
  357. + {
  358. + GGML_ABORT("fatal error");
  359. + }
  360. + }
  361. +}
  362. // ggml_compute_forward_arange
  363. @@ -17294,6 +17374,10 @@ static void ggml_compute_forward(struct ggml_compute_params * params, struct ggm
  364. {
  365. ggml_compute_forward_pad(params, tensor);
  366. } break;
  367. + case GGML_OP_UNPAD:
  368. + {
  369. + ggml_compute_forward_unpad(params, tensor);
  370. + } break;
  371. case GGML_OP_ARANGE:
  372. {
  373. ggml_compute_forward_arange(params, tensor);
  374. @@ -18369,6 +18453,10 @@ static void ggml_compute_backward(struct ggml_context * ctx, struct ggml_tensor
  375. {
  376. GGML_ABORT("fatal error"); // TODO: not implemented
  377. }
  378. + case GGML_OP_UNPAD:
  379. + {
  380. + GGML_ABORT("fatal error"); // TODO: not implemented
  381. + }
  382. case GGML_OP_ARANGE:
  383. {
  384. GGML_ABORT("fatal error"); // TODO: not implemented
  385. @@ -19165,6 +19253,7 @@ static int ggml_get_n_tasks(struct ggml_tensor * node, int n_threads) {
  386. } break;
  387. case GGML_OP_UPSCALE:
  388. case GGML_OP_PAD:
  389. + case GGML_OP_UNPAD:
  390. case GGML_OP_ARANGE:
  391. case GGML_OP_TIMESTEP_EMBEDDING:
  392. case GGML_OP_ARGSORT: