Skip to content

Commit 12d8cd6

Browse files
author
Judd
committed
add ggml_backend_sched_dump_dot
1 parent 56eea07 commit 12d8cd6

File tree

4 files changed

+209
-4
lines changed

4 files changed

+209
-4
lines changed

ggml/include/ggml-backend.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -347,6 +347,9 @@ extern "C" {
347347
GGML_API ggml_backend_buffer_t ggml_backend_cpu_buffer_from_ptr(void * ptr, size_t size);
348348
GGML_API ggml_backend_buffer_type_t ggml_backend_cpu_buffer_type(void);
349349

350+
GGML_API void ggml_backend_sched_splits_fdump_dot(FILE * fp, ggml_backend_sched_t sched, const struct ggml_cgraph * graph);
351+
GGML_API void ggml_backend_sched_dump_dot(ggml_backend_sched_t sched, const struct ggml_cgraph * graph, const char * filename);
352+
350353
#ifdef __cplusplus
351354
}
352355
#endif

ggml/src/ggml-backend.cpp

Lines changed: 198 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,15 @@
1414
#include "ggml-impl.h"
1515

1616
#include <assert.h>
17+
#include <inttypes.h>
1718
#include <limits.h>
1819
#include <stdarg.h>
1920
#include <stdio.h>
2021
#include <stdlib.h>
2122
#include <string.h>
2223
#include <string>
2324
#include <vector>
25+
#include <set>
2426

2527
#ifdef __APPLE__
2628
#include <sys/types.h>
@@ -1997,3 +1999,199 @@ ggml_backend_buffer_t ggml_backend_cpu_buffer_from_ptr(void * ptr, size_t size)
19971999
GGML_ASSERT((uintptr_t)ptr % TENSOR_ALIGNMENT == 0 && "buffer pointer must be aligned");
19982000
return ggml_backend_buffer_init(ggml_backend_cpu_buffer_from_ptr_type(), ggml_backend_cpu_buffer_from_ptr_i, ptr, size);
19992001
}
2002+
2003+
void ggml_backend_sched_splits_fdump_dot(FILE * fp, ggml_backend_sched_t sched, const struct ggml_cgraph * graph) {
2004+
std::set<void *> visited;
2005+
2006+
for (int i = 0; i < sched->n_splits; i++) {
2007+
struct ggml_backend_sched_split * split = &sched->splits[i];
2008+
ggml_backend_t split_backend = sched->backends[split->backend_id];
2009+
2010+
fprintf(fp, " subgraph cluster_%d {"
2011+
" node [style=filled];"
2012+
" label = \"SPLIT %d : %s # %d inputs\";\n",
2013+
i, i, ggml_backend_name(split_backend), split->n_inputs);
2014+
2015+
for (int j = split->i_start; j < split->i_end; j++) {
2016+
struct ggml_tensor *node = graph->nodes[j];
2017+
fprintf(fp, " \"%p\";\n", node);
2018+
for (int k = 0; k < GGML_MAX_SRC; k++) {
2019+
struct ggml_tensor *src = node->src[k];
2020+
if ( (nullptr == src)
2021+
|| (tensor_backend_id(src) != split->backend_id)
2022+
|| (visited.find(src) != visited.end())) {
2023+
continue;
2024+
}
2025+
2026+
visited.insert(src);
2027+
fprintf(fp, " \"%p\";\n", src);
2028+
}
2029+
}
2030+
fprintf(fp, " }\n");
2031+
}
2032+
}
2033+
2034+
static uint32_t simple_hash(const unsigned char *str)
2035+
{
2036+
uint32_t hash = 5381;
2037+
while (unsigned char c = *str++) hash = hash * 33 + c;
2038+
return hash;
2039+
}
2040+
2041+
static const char *ggml_color_of_backend(ggml_backend_sched_t sched, struct ggml_tensor * node) {
2042+
#ifndef GGML_DOT_FULL_COLOR
2043+
#define COLOR_NUM 12
2044+
#define DEF_COLOR 0
2045+
#else
2046+
#define COLOR_NUM 0x1000000
2047+
#define DEF_COLOR 0x0ffffff
2048+
#endif
2049+
2050+
static char color[32];
2051+
uint32_t color1 = DEF_COLOR;
2052+
uint32_t color2 = DEF_COLOR;
2053+
2054+
ggml_backend_t backend = ggml_backend_sched_get_tensor_backend(sched, node);
2055+
if (backend) {
2056+
const char *name = ggml_backend_name(backend);
2057+
color1 = simple_hash((const unsigned char *)name) % COLOR_NUM;
2058+
color2 = color1;
2059+
}
2060+
if (node->buffer) {
2061+
ggml_backend_buffer_type_t buft = node->buffer->buft;
2062+
if (backend && !ggml_backend_supports_buft(backend, buft)) {
2063+
color2 = simple_hash((const unsigned char *)ggml_backend_buft_name(buft)) % COLOR_NUM;
2064+
if (color2 == color1) color2 = (~color1) % COLOR_NUM;
2065+
}
2066+
}
2067+
#ifndef GGML_DOT_FULL_COLOR
2068+
snprintf(color, sizeof(color), "%d;0.5:%d", color1 + 1, color2 + 1);
2069+
#else
2070+
snprintf(color, sizeof(color), "#%06x;0.5:#%06x", color1, color2);
2071+
#endif
2072+
return color;
2073+
}
2074+
2075+
static void ggml_graph_dump_dot_leaf(ggml_backend_sched_t sched, FILE * fp, std::set<void *> &visited_nodes, struct ggml_tensor * node, struct ggml_tensor *parent, const char *label, const int i) {
2076+
if (visited_nodes.find(node) != visited_nodes.end()) {
2077+
goto draw_edge;
2078+
}
2079+
2080+
visited_nodes.insert(node);
2081+
2082+
fprintf(fp, " \"%p\" [ style = filled; fillcolor = \"%s\"; shape = record; label=\"<x>",
2083+
(void *)node, ggml_color_of_backend(sched, node));
2084+
2085+
if (strlen(node->name) > 0) {
2086+
fprintf(fp, "%s (%s)|", node->name, ggml_type_name(node->type));
2087+
} else {
2088+
fprintf(fp, "(%s)|", ggml_type_name(node->type));
2089+
}
2090+
2091+
fprintf(fp, "CONST %d [%" PRId64 ", %" PRId64 "]", i, node->ne[0], node->ne[1]);
2092+
fprintf(fp, "\"; ]\n");
2093+
2094+
draw_edge:
2095+
if (parent) {
2096+
ggml_graph_dump_dot_leaf_edge(fp, parent, node, label);
2097+
}
2098+
if (node->view_src) {
2099+
ggml_graph_dump_dot_leaf_edge(fp, node, node->view_src, label);
2100+
}
2101+
}
2102+
2103+
static void ggml_graph_dump_dot_node(ggml_backend_sched_t sched, FILE * fp, std::set<void *> &visited_nodes, const struct ggml_cgraph * graph, struct ggml_tensor * node, struct ggml_tensor *child, const char *label, const int i);
2104+
2105+
static void ggml_graph_dump_dot_real_node(ggml_backend_sched_t sched, FILE * fp, std::set<void *> &visited_nodes, const struct ggml_cgraph * graph, struct ggml_tensor * node, struct ggml_tensor *child, const char *label, const int i) {
2106+
char color[16];
2107+
struct ggml_tensor * grad = nullptr;
2108+
2109+
if (visited_nodes.find(node) != visited_nodes.end()) {
2110+
goto draw_edge;
2111+
}
2112+
2113+
visited_nodes.insert(node);
2114+
2115+
grad = ggml_graph_get_grad(graph, node);
2116+
2117+
if (node->flags & GGML_TENSOR_FLAG_PARAM) {
2118+
snprintf(color, sizeof(color), "yellow");
2119+
} else if (grad) {
2120+
snprintf(color, sizeof(color), "lightblue");
2121+
} else {
2122+
snprintf(color, sizeof(color), "white");
2123+
}
2124+
2125+
fprintf(fp, " \"%p\" [ style = filled; fillcolor = \"%s\"; shape = record; label=\"",
2126+
(void *) node, ggml_color_of_backend(sched, node));
2127+
2128+
if (strlen(node->name) > 0) {
2129+
fprintf(fp, "%s (%s)|", node->name, ggml_type_name(node->type));
2130+
} else {
2131+
fprintf(fp, "(%s)|", ggml_type_name(node->type));
2132+
}
2133+
2134+
if (ggml_is_matrix(node)) {
2135+
fprintf(fp, "%d [%" PRId64 ", %" PRId64 "] | <x>%s", i, node->ne[0], node->ne[1], ggml_op_symbol(node->op));
2136+
} else {
2137+
fprintf(fp, "%d [%" PRId64 ", %" PRId64 ", %" PRId64 "] | <x>%s", i, node->ne[0], node->ne[1], node->ne[2], ggml_op_symbol(node->op));
2138+
}
2139+
2140+
if (grad) {
2141+
fprintf(fp, " | <g>%s\"; ]\n", ggml_op_symbol(grad->op));
2142+
} else {
2143+
fprintf(fp, "\"; ]\n");
2144+
}
2145+
2146+
for (int j = 0; j < GGML_MAX_SRC; j++) {
2147+
if (node->src[j]) {
2148+
char label[16];
2149+
snprintf(label, sizeof(label), "src %d", j);
2150+
ggml_graph_dump_dot_node(sched, fp, visited_nodes, graph, node->src[j], node, label, -1);
2151+
}
2152+
}
2153+
2154+
draw_edge:
2155+
if (child) {
2156+
ggml_graph_dump_dot_node_edge(fp, graph, child, node, label);
2157+
}
2158+
}
2159+
2160+
static void ggml_graph_dump_dot_node(ggml_backend_sched_t sched, FILE * fp, std::set<void *> &visited_nodes, const struct ggml_cgraph * graph, struct ggml_tensor * node, struct ggml_tensor *child, const char *label, const int i) {
2161+
if ((node->op == GGML_OP_NONE) && !(node->flags & GGML_TENSOR_FLAG_PARAM)) {
2162+
ggml_graph_dump_dot_leaf(sched, fp, visited_nodes, node, child, label, i);
2163+
} else {
2164+
ggml_graph_dump_dot_real_node(sched, fp, visited_nodes, graph, node, child, label, i);
2165+
}
2166+
}
2167+
2168+
void ggml_backend_sched_dump_dot(ggml_backend_sched_t sched, const struct ggml_cgraph * graph, const char * filename) {
2169+
FILE * fp = ggml_fopen(filename, "w");
2170+
GGML_ASSERT(fp);
2171+
2172+
std::set<void *> visited_nodes;
2173+
2174+
fprintf(fp, "digraph G {\n");
2175+
#ifndef GGML_DOT_FULL_COLOR
2176+
fprintf(fp, "node [colorscheme=set312]\n");
2177+
#endif
2178+
fprintf(fp, " newrank = true;\n");
2179+
fprintf(fp, " rankdir = TB;\n");
2180+
2181+
for (int i = 0; i < graph->n_nodes; i++) {
2182+
struct ggml_tensor * node = graph->nodes[i];
2183+
2184+
if (ggml_graph_get_parent(graph, node)) {
2185+
continue;
2186+
}
2187+
2188+
ggml_graph_dump_dot_node(sched, fp, visited_nodes, graph, node, NULL, NULL, i);
2189+
}
2190+
2191+
ggml_backend_sched_splits_fdump_dot(fp, sched, graph);
2192+
2193+
fprintf(fp, "}\n");
2194+
fclose(fp);
2195+
2196+
GGML_LOG_INFO("%s: dot -Tpng %s -o %s.png && open %s.png\n", __func__, filename, filename, filename);
2197+
}

ggml/src/ggml-impl.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -551,6 +551,10 @@ static inline ggml_bf16_t ggml_compute_fp32_to_bf16(float s) {
551551
#define GGML_FP32_TO_BF16(x) ggml_compute_fp32_to_bf16(x)
552552
#define GGML_BF16_TO_FP32(x) ggml_compute_bf16_to_fp32(x)
553553

554+
struct ggml_tensor * ggml_graph_get_parent(const struct ggml_cgraph * cgraph, const struct ggml_tensor * node);
555+
void ggml_graph_dump_dot_leaf_edge(FILE * fp, struct ggml_tensor * node, struct ggml_tensor * parent, const char * label);
556+
void ggml_graph_dump_dot_node_edge(FILE * fp, const struct ggml_cgraph * gb, struct ggml_tensor * node, struct ggml_tensor * parent, const char * label);
557+
554558
#ifdef __cplusplus
555559
}
556560
#endif

ggml/src/ggml.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5987,7 +5987,7 @@ struct ggml_tensor * ggml_graph_get_tensor(const struct ggml_cgraph * cgraph, co
59875987

59885988
struct ggml_tensor * ggml_graph_get_grad(const struct ggml_cgraph * cgraph, const struct ggml_tensor * node) {
59895989
const size_t igrad = ggml_hash_find(&cgraph->visited_hash_set, node);
5990-
return igrad != GGML_HASHSET_FULL && ggml_bitset_get(cgraph->visited_hash_set.used, igrad) ? cgraph->grads[igrad] : NULL;
5990+
return igrad != GGML_HASHSET_FULL && ggml_bitset_get(cgraph->visited_hash_set.used, igrad) && cgraph->grads ? cgraph->grads[igrad] : NULL;
59915991
}
59925992

59935993
struct ggml_tensor * ggml_graph_get_grad_acc(const struct ggml_cgraph * cgraph, const struct ggml_tensor * node) {
@@ -6038,7 +6038,7 @@ static bool ggml_graph_find(const struct ggml_cgraph * cgraph, const struct ggml
60386038
return false;
60396039
}
60406040

6041-
static struct ggml_tensor * ggml_graph_get_parent(const struct ggml_cgraph * cgraph, const struct ggml_tensor * node) {
6041+
struct ggml_tensor * ggml_graph_get_parent(const struct ggml_cgraph * cgraph, const struct ggml_tensor * node) {
60426042
for (int i = 0; i < cgraph->n_nodes; i++) {
60436043
struct ggml_tensor * parent = cgraph->nodes[i];
60446044
struct ggml_tensor * grad = ggml_graph_get_grad(cgraph, parent);
@@ -6051,7 +6051,7 @@ static struct ggml_tensor * ggml_graph_get_parent(const struct ggml_cgraph * cgr
60516051
return NULL;
60526052
}
60536053

6054-
static void ggml_graph_dump_dot_node_edge(FILE * fp, const struct ggml_cgraph * gb, struct ggml_tensor * node, struct ggml_tensor * parent, const char * label) {
6054+
void ggml_graph_dump_dot_node_edge(FILE * fp, const struct ggml_cgraph * gb, struct ggml_tensor * node, struct ggml_tensor * parent, const char * label) {
60556055
struct ggml_tensor * gparent = ggml_graph_get_parent(gb, node);
60566056
struct ggml_tensor * gparent0 = ggml_graph_get_parent(gb, parent);
60576057
fprintf(fp, " \"%p\":%s -> \"%p\":%s [ arrowhead = %s; style = %s; label = \"%s\"; ]\n",
@@ -6064,7 +6064,7 @@ static void ggml_graph_dump_dot_node_edge(FILE * fp, const struct ggml_cgraph *
60646064
label);
60656065
}
60666066

6067-
static void ggml_graph_dump_dot_leaf_edge(FILE * fp, struct ggml_tensor * node, struct ggml_tensor * parent, const char * label) {
6067+
void ggml_graph_dump_dot_leaf_edge(FILE * fp, struct ggml_tensor * node, struct ggml_tensor * parent, const char * label) {
60686068
fprintf(fp, " \"%p\":%s -> \"%p\":%s [ label = \"%s\"; ]\n",
60696069
(void *) parent, "x",
60706070
(void *) node, "x",

0 commit comments

Comments
 (0)