Skip to content

Commit dc2cbce

Browse files
authored
Test ggml compute chunks (ggml-org#16)
* chunked RMS and mulmat for testing * linux compilation fix - not super clean
1 parent a584364 commit dc2cbce

3 files changed

Lines changed: 100 additions & 50 deletions

File tree

ggml.c

Lines changed: 79 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -44,9 +44,10 @@
4444
#if defined(_WIN32)
4545

4646
#include <windows.h>
47-
47+
#ifndef atomic_int
4848
typedef volatile LONG atomic_int;
4949
typedef atomic_int atomic_bool;
50+
#endif
5051

5152
static void atomic_store(atomic_int* ptr, LONG val) {
5253
InterlockedExchange(ptr, val);
@@ -3761,9 +3762,6 @@ struct ggml_context_container {
37613762
struct ggml_context context;
37623763
};
37633764

3764-
//
3765-
// ggml state
3766-
//
37673765

37683766
struct ggml_state {
37693767
struct ggml_context_container contexts[GGML_MAX_CONTEXTS];
@@ -9939,18 +9937,20 @@ static void ggml_compute_forward_rms_norm_f32(
99399937
GGML_ASSERT(ggml_are_same_shape(src0, dst));
99409938

99419939
if (params->type == GGML_TASK_INIT || params->type == GGML_TASK_FINALIZE) {
9940+
atomic_store(params->aic, 0);
9941+
99429942
return;
99439943
}
99449944

99459945
GGML_ASSERT(src0->nb[0] == sizeof(float));
99469946

9947-
const int ith = params->ith;
9947+
const int ith = params->ith; UNUSED(ith);
99489948
const int nth = params->nth;
99499949

99509950
const int64_t ne00 = src0->ne[0];
99519951
const int64_t ne01 = src0->ne[1];
99529952
const int64_t ne02 = src0->ne[2];
9953-
const int64_t ne03 = src0->ne[3];
9953+
const int64_t ne03 = src0->ne[3]; UNUSED(ne03);
99549954

99559955
const size_t nb01 = src0->nb[1];
99569956
const size_t nb02 = src0->nb[2];
@@ -9962,30 +9962,45 @@ static void ggml_compute_forward_rms_norm_f32(
99629962

99639963
const float eps = 1e-6f; // TODO: make this a parameter
99649964

9965-
// TODO: optimize
9966-
for (int64_t i03 = 0; i03 < ne03; i03++) {
9967-
for (int64_t i02 = 0; i02 < ne02; i02++) {
9968-
for (int64_t i01 = ith; i01 < ne01; i01 += nth) {
9969-
const float * x = (float *) ((char *) src0->data + i01*nb01 + i02*nb02 + i03*nb03);
9970-
9971-
ggml_float sum = 0.0;
9972-
for (int64_t i00 = 0; i00 < ne00; i00++) {
9973-
sum += (ggml_float)(x[i00] * x[i00]);
9974-
}
9965+
const int nr = ggml_nrows(src0);
9966+
const int dr = (nr + 8*nth - 1)/(8*nth);
99759967

9976-
const float mean = sum/ne00;
9968+
while (true) {
9969+
const int ir0 = atomic_fetch_add(params->aic, dr);
99779970

9978-
float * y = (float *) ((char *) dst->data + i01*nb1 + i02*nb2 + i03*nb3);
9971+
for (int ir = ir0; ir < ir0 + dr; ++ir) {
9972+
if (ir >= nr) {
9973+
break;
9974+
}
99799975

9980-
memcpy(y, x, ne00 * sizeof(float));
9981-
// for (int i00 = 0; i00 < ne00; i00++) {
9982-
// y[i00] = x[i00];
9983-
// }
9976+
// src0 indices
9977+
const int i03 = ir/(ne02*ne01);
9978+
const int i02 = (ir - i03*ne02*ne01)/ne01;
9979+
const int i01 = (ir - i03*ne02*ne01 - i02*ne01);
99849980

9985-
const float scale = 1.0f/sqrtf(mean + eps);
9981+
const float * x = (float *) ((char *) src0->data + i01*nb01 + i02*nb02 + i03*nb03);
99869982

9987-
ggml_vec_scale_f32(ne00, y, scale);
9983+
ggml_float sum = 0.0;
9984+
for (int64_t i00 = 0; i00 < ne00; i00++) {
9985+
sum += (ggml_float)(x[i00] * x[i00]);
99889986
}
9987+
9988+
float mean = sum/ne00;
9989+
9990+
float * y = (float *) ((char *) dst->data + i01*nb1 + i02*nb2 + i03*nb3);
9991+
9992+
memcpy(y, x, ne00 * sizeof(float));
9993+
// for (int i00 = 0; i00 < ne00; i00++) {
9994+
// y[i00] = x[i00];
9995+
// }
9996+
9997+
const float scale = 1.0f/sqrtf(mean + eps);
9998+
9999+
ggml_vec_scale_f32(ne00, y, scale);
10000+
}
10001+
10002+
if (ir0 + dr >= nr) {
10003+
break;
998910004
}
999010005
}
999110006
}
@@ -10635,7 +10650,7 @@ static void ggml_compute_forward_mul_mat_q_f32(
1063510650
const int nb2 = dst->nb[2];
1063610651
const int nb3 = dst->nb[3];
1063710652

10638-
const int ith = params->ith;
10653+
const int ith = params->ith; UNUSED(ith);
1063910654
const int nth = params->nth;
1064010655

1064110656
GGML_ASSERT(ne02 == ne12);
@@ -10737,50 +10752,57 @@ static void ggml_compute_forward_mul_mat_q_f32(
1073710752
}
1073810753
}
1073910754

10755+
atomic_store(params->aic, 0);
10756+
1074010757
return;
1074110758
}
1074210759

1074310760
if (params->type == GGML_TASK_FINALIZE) {
1074410761
return;
1074510762
}
1074610763

10764+
void * wdata = params->wdata;
10765+
const size_t row_size = ne00*GGML_TYPE_SIZE[vec_dot_type]/GGML_BLCK_SIZE[vec_dot_type];
10766+
1074710767
// parallelize by src0 rows using ggml_vec_dot_q
1074810768

10749-
// total rows in src0
10750-
const int nr = ne01*ne02*ne03;
10769+
const int nr = ggml_nrows(src0); // nr stands for number of rows
10770+
const int dr = (nr + 8*nth - 1)/(8*nth); // dr stands for delta rows
1075110771

10752-
// rows per thread
10753-
const int dr = (nr + nth - 1)/nth;
10772+
while (true) {
10773+
const int ir0 = atomic_fetch_add(params->aic, dr);
1075410774

10755-
// row range for this thread
10756-
const int ir0 = dr*ith;
10757-
const int ir1 = MIN(ir0 + dr, nr);
10775+
for (int ir = ir0; ir < ir0 + dr; ++ir) {
10776+
if (ir >= nr) {
10777+
break;
10778+
}
1075810779

10759-
void * wdata = params->wdata;
10760-
const size_t row_size = ne00*GGML_TYPE_SIZE[vec_dot_type]/GGML_BLCK_SIZE[vec_dot_type];
10780+
// src0 indices
10781+
const int i03 = ir/(ne02*ne01);
10782+
const int i02 = (ir - i03*ne02*ne01)/ne01;
10783+
const int i01 = (ir - i03*ne02*ne01 - i02*ne01);
1076110784

10762-
for (int ir = ir0; ir < ir1; ++ir) {
10763-
// src0 indices
10764-
const int i03 = ir/(ne02*ne01);
10765-
const int i02 = (ir - i03*ne02*ne01)/ne01;
10766-
const int i01 = (ir - i03*ne02*ne01 - i02*ne01);
10785+
const int i13 = i03;
10786+
const int i12 = i02;
1076710787

10768-
const int i13 = i03;
10769-
const int i12 = i02;
10788+
const int i0 = i01;
10789+
const int i2 = i02;
10790+
const int i3 = i03;
1077010791

10771-
const int i0 = i01;
10772-
const int i2 = i02;
10773-
const int i3 = i03;
10792+
void * src0_row = (void *) ((char *) src0->data + (i01*nb01 + i02*nb02 + i03*nb03));
10793+
char * src1_col = ((char *) wdata + ( (0 + i12*ne11 + i13*ne12*ne11)*row_size));
1077410794

10775-
void * src0_row = (void *) ((char *) src0->data + (i01*nb01 + i02*nb02 + i03*nb03));
10776-
char * src1_col = ((char *) wdata + ( (0 + i12*ne11 + i13*ne12*ne11)*row_size));
10795+
float * dst_col = (float *) ((char *) dst->data + (i0*nb0 + 0*nb1 + i2*nb2 + i3*nb3));
1077710796

10778-
float * dst_col = (float *) ((char *) dst->data + (i0*nb0 + 0*nb1 + i2*nb2 + i3*nb3));
10797+
assert(ne00 % 32 == 0);
1077910798

10780-
assert(ne00 % 32 == 0);
10799+
for (int64_t ic = 0; ic < ne11; ++ic) {
10800+
vec_dot_q(ne00, &dst_col[ic*ne0], src0_row, (void *) (src1_col + ic*row_size));
10801+
}
10802+
}
1078110803

10782-
for (int64_t ic = 0; ic < ne11; ++ic) {
10783-
vec_dot_q(ne00, &dst_col[ic*ne0], src0_row, (void *) (src1_col + ic*row_size));
10804+
if (ir0 + dr >= nr) {
10805+
break;
1078410806
}
1078510807
}
1078610808

@@ -15879,6 +15901,7 @@ struct ggml_compute_state_shared {
1587915901

1588015902
// synchronization primitives
1588115903
atomic_int n_ready;
15904+
atomic_int aic;
1588215905
atomic_bool has_work;
1588315906
atomic_bool stop; // stop all threads
1588415907
};
@@ -15947,6 +15970,7 @@ void ggml_graph_compute(struct ggml_context * ctx, struct ggml_cgraph * cgraph)
1594715970
/*.spin =*/ GGML_LOCK_INITIALIZER,
1594815971
/*.n_threads =*/ n_threads,
1594915972
/*.n_ready =*/ 0,
15973+
/*.aic =*/ 0,
1595015974
/*.has_work =*/ false,
1595115975
/*.stop =*/ false,
1595215976
};
@@ -15967,6 +15991,7 @@ void ggml_graph_compute(struct ggml_context * ctx, struct ggml_cgraph * cgraph)
1596715991
.nth = n_threads,
1596815992
.wsize = cgraph->work ? ggml_nbytes(cgraph->work) : 0,
1596915993
.wdata = cgraph->work ? cgraph->work->data : NULL,
15994+
.aic = &state_shared.aic,
1597015995
},
1597115996
.node = NULL,
1597215997
.shared = &state_shared,
@@ -16308,6 +16333,7 @@ void ggml_graph_compute(struct ggml_context * ctx, struct ggml_cgraph * cgraph)
1630816333
/*.nth =*/ node->n_tasks,
1630916334
/*.wsize =*/ cgraph->work ? ggml_nbytes(cgraph->work) : 0,
1631016335
/*.wdata =*/ cgraph->work ? cgraph->work->data : NULL,
16336+
/*.aic =*/ &state_shared.aic,
1631116337
};
1631216338

1631316339
ggml_compute_forward(&params, node);
@@ -16331,6 +16357,7 @@ void ggml_graph_compute(struct ggml_context * ctx, struct ggml_cgraph * cgraph)
1633116357
.nth = node->n_tasks,
1633216358
.wsize = cgraph->work ? ggml_nbytes(cgraph->work) : 0,
1633316359
.wdata = cgraph->work ? cgraph->work->data : NULL,
16360+
.aic = &state_shared.aic,
1633416361
};
1633516362
workers[j].node = node;
1633616363
}
@@ -16346,6 +16373,7 @@ void ggml_graph_compute(struct ggml_context * ctx, struct ggml_cgraph * cgraph)
1634616373
}
1634716374

1634816375
params.type = GGML_TASK_COMPUTE;
16376+
params.aic = &state_shared.aic;
1634916377
ggml_compute_forward(&params, node);
1635016378

1635116379
// wait for thread pool
@@ -16386,6 +16414,7 @@ void ggml_graph_compute(struct ggml_context * ctx, struct ggml_cgraph * cgraph)
1638616414
.nth = node->n_tasks,
1638716415
.wsize = cgraph->work ? ggml_nbytes(cgraph->work) : 0,
1638816416
.wdata = cgraph->work ? cgraph->work->data : NULL,
16417+
.aic = &state_shared.aic,
1638916418
};
1639016419
workers[j].node = node;
1639116420
}

ggml.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,18 @@ extern "C" {
220220
typedef uint16_t ggml_fp16_t;
221221
#endif
222222

223+
// we need atomic support for the param struct - this needs to be improved
224+
#if defined(_WIN32)
225+
typedef volatile long atomic_int;
226+
typedef atomic_int atomic_bool;
227+
#else
228+
#ifndef __cplusplus
229+
#include <stdatomic.h>
230+
#else
231+
typedef volatile long atomic_int;
232+
typedef atomic_int atomic_bool;
233+
#endif
234+
#endif
223235
// convert FP16 <-> FP32
224236
GGML_API float ggml_fp16_to_fp32(ggml_fp16_t x);
225237
GGML_API ggml_fp16_t ggml_fp32_to_fp16(float x);
@@ -454,8 +466,12 @@ extern "C" {
454466
// work buffer for all threads
455467
size_t wsize;
456468
void * wdata;
469+
470+
// atomic counter used to distribute chunks of work
471+
atomic_int * aic;
457472
};
458473

474+
459475
// misc
460476

461477
GGML_API void ggml_time_init(void); // call this once at the beginning of the program

libfalcon.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,11 @@
4545
#include <sstream>
4646
#include <numeric>
4747

48+
#if defined(_MSC_VER)
49+
// disable "possible loss of data"
50+
#pragma warning(disable: 4244 4267)
51+
#endif
52+
4853
#define LLAMA_USE_SCRATCH
4954
#define LLAMA_MAX_SCRATCH_BUFFERS 16
5055

0 commit comments

Comments
 (0)