Skip to content

Commit 9d7cb80

Browse files
Aclyggerganov
authored andcommitted
ggml-cpu : "align corners" for bilinear upscale/downscale (ggml/1285)
* add "align corners" mode for bilinear upscale, and allow downscaling * add ggml_interpolate, deprecate ggml_upscale_ext, pass in align-corners as bit-flag * test-backend-ops: replace ggml_upscale_ext with ggml_interpolate, add test cases for downscale and align-corners
1 parent 515df20 commit 9d7cb80

File tree

3 files changed

+56
-24
lines changed

3 files changed

+56
-24
lines changed

ggml/include/ggml.h

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1765,6 +1765,12 @@ extern "C" {
17651765
enum ggml_scale_mode {
17661766
GGML_SCALE_MODE_NEAREST = 0,
17671767
GGML_SCALE_MODE_BILINEAR = 1,
1768+
1769+
GGML_SCALE_MODE_COUNT
1770+
};
1771+
1772+
enum ggml_scale_flag {
1773+
GGML_SCALE_FLAG_ALIGN_CORNERS = (1 << 8)
17681774
};
17691775

17701776
// interpolate
@@ -1777,14 +1783,26 @@ extern "C" {
17771783

17781784
// interpolate
17791785
// interpolate scale to specified dimensions
1780-
GGML_API struct ggml_tensor * ggml_upscale_ext(
1786+
GGML_DEPRECATED(GGML_API struct ggml_tensor * ggml_upscale_ext(
17811787
struct ggml_context * ctx,
17821788
struct ggml_tensor * a,
17831789
int ne0,
17841790
int ne1,
17851791
int ne2,
17861792
int ne3,
1787-
enum ggml_scale_mode mode);
1793+
enum ggml_scale_mode mode),
1794+
"use ggml_interpolate instead");
1795+
1796+
// Up- or downsamples the input to the specified size.
1797+
// 2D scale modes (eg. bilinear) are applied to the first two dimensions.
1798+
GGML_API struct ggml_tensor * ggml_interpolate(
1799+
struct ggml_context * ctx,
1800+
struct ggml_tensor * a,
1801+
int64_t ne0,
1802+
int64_t ne1,
1803+
int64_t ne2,
1804+
int64_t ne3,
1805+
uint32_t mode); // ggml_scale_mode [ | ggml_scale_flag...]
17881806

17891807
// pad each dimension with zeros: [x, ..., x] -> [x, ..., x, 0, ..., 0]
17901808
GGML_API struct ggml_tensor * ggml_pad(

ggml/src/ggml-cpu/ops.cpp

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6608,12 +6608,13 @@ static void ggml_compute_forward_upscale_f32(
66086608

66096609
GGML_TENSOR_UNARY_OP_LOCALS
66106610

6611-
const float sf0 = (float)ne0/src0->ne[0];
6612-
const float sf1 = (float)ne1/src0->ne[1];
6613-
const float sf2 = (float)ne2/src0->ne[2];
6614-
const float sf3 = (float)ne3/src0->ne[3];
6611+
float sf0 = (float)ne0/src0->ne[0];
6612+
float sf1 = (float)ne1/src0->ne[1];
6613+
float sf2 = (float)ne2/src0->ne[2];
6614+
float sf3 = (float)ne3/src0->ne[3];
66156615

6616-
const ggml_scale_mode mode = (ggml_scale_mode) ggml_get_op_params_i32(dst, 0);
6616+
const int32_t mode_flags = ggml_get_op_params_i32(dst, 0);
6617+
const ggml_scale_mode mode = (ggml_scale_mode) (mode_flags & 0xFF);
66176618

66186619
if (mode == GGML_SCALE_MODE_NEAREST) {
66196620
for (int64_t i3 = 0; i3 < ne3; i3++) {
@@ -6634,8 +6635,12 @@ static void ggml_compute_forward_upscale_f32(
66346635
}
66356636
}
66366637
} else if (mode == GGML_SCALE_MODE_BILINEAR) {
6637-
// setting a pixel offset of 0 would replicate the behavior of pytorch interpolate with align_corners=True
6638-
const float pixel_offset = 0.5f;
6638+
float pixel_offset = 0.5f;
6639+
if (mode_flags & GGML_SCALE_FLAG_ALIGN_CORNERS) {
6640+
pixel_offset = 0.0f;
6641+
sf0 = (float)(ne0 - 1) / (src0->ne[0] - 1);
6642+
sf1 = (float)(ne1 - 1) / (src0->ne[1] - 1);
6643+
}
66396644

66406645
for (int64_t i3 = 0; i3 < ne3; i3++) {
66416646
const int64_t i03 = i3 / sf3;

ggml/src/ggml.c

Lines changed: 24 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4247,24 +4247,21 @@ struct ggml_tensor * ggml_pool_2d_back(
42474247
return result;
42484248
}
42494249

4250-
// ggml_upscale
4250+
// ggml_upscale / ggml_interpolate
42514251

4252-
static struct ggml_tensor * ggml_upscale_impl(
4252+
static struct ggml_tensor * ggml_interpolate_impl(
42534253
struct ggml_context * ctx,
42544254
struct ggml_tensor * a,
4255-
int ne0,
4256-
int ne1,
4257-
int ne2,
4258-
int ne3,
4259-
enum ggml_scale_mode mode) {
4260-
GGML_ASSERT(a->ne[0] <= ne0);
4261-
GGML_ASSERT(a->ne[1] <= ne1);
4262-
GGML_ASSERT(a->ne[2] <= ne2);
4263-
GGML_ASSERT(a->ne[3] <= ne3);
4264-
4255+
int64_t ne0,
4256+
int64_t ne1,
4257+
int64_t ne2,
4258+
int64_t ne3,
4259+
uint32_t mode) {
4260+
GGML_ASSERT((mode & 0xFF) < GGML_SCALE_MODE_COUNT);
4261+
42654262
struct ggml_tensor * result = ggml_new_tensor_4d(ctx, a->type, ne0, ne1, ne2, ne3);
42664263

4267-
ggml_set_op_params_i32(result, 0, mode);
4264+
ggml_set_op_params_i32(result, 0, (int32_t)mode);
42684265

42694266
result->op = GGML_OP_UPSCALE;
42704267
result->src[0] = a;
@@ -4277,7 +4274,8 @@ struct ggml_tensor * ggml_upscale(
42774274
struct ggml_tensor * a,
42784275
int scale_factor,
42794276
enum ggml_scale_mode mode) {
4280-
return ggml_upscale_impl(ctx, a, a->ne[0] * scale_factor, a->ne[1] * scale_factor, a->ne[2], a->ne[3], mode);
4277+
GGML_ASSERT(scale_factor > 1);
4278+
return ggml_interpolate_impl(ctx, a, a->ne[0] * scale_factor, a->ne[1] * scale_factor, a->ne[2], a->ne[3], mode);
42814279
}
42824280

42834281
struct ggml_tensor * ggml_upscale_ext(
@@ -4288,7 +4286,18 @@ struct ggml_tensor * ggml_upscale_ext(
42884286
int ne2,
42894287
int ne3,
42904288
enum ggml_scale_mode mode) {
4291-
return ggml_upscale_impl(ctx, a, ne0, ne1, ne2, ne3, mode);
4289+
return ggml_interpolate_impl(ctx, a, ne0, ne1, ne2, ne3, mode);
4290+
}
4291+
4292+
struct ggml_tensor * ggml_interpolate(
4293+
struct ggml_context * ctx,
4294+
struct ggml_tensor * a,
4295+
int64_t ne0,
4296+
int64_t ne1,
4297+
int64_t ne2,
4298+
int64_t ne3,
4299+
uint32_t mode) {
4300+
return ggml_interpolate_impl(ctx, a, ne0, ne1, ne2, ne3, mode);
42924301
}
42934302

42944303
// ggml_pad

0 commit comments

Comments
 (0)