Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

.dot file of ggml_graph can not be generated to .png file #589

Closed
Alwaysion opened this issue Mar 29, 2023 · 4 comments
Closed

.dot file of ggml_graph can not be generated to .png file #589

Alwaysion opened this issue Mar 29, 2023 · 4 comments

Comments

@Alwaysion
Copy link

Hi, I want to generate a picture of the grapj. And I uncommented this 2 lines in "llama.cpp", so that to run the function ggml_graph_dump_dot()

    //if (n_past%100 == 0) {
        ggml_graph_print   (&gf);
        ggml_graph_dump_dot(&gf, NULL, "gpt-2.dot");
    //}

And I got a file named gpt-2.dot
But when I run command in python:

from graphviz import Digraph
import sys
sys.setrecursionlimit(300000) 

import pydot
import os
(graph,) = pydot.graph_from_dot_file("D:\\PIQ\\llama.cpp\\build\\examples\\main\\gpt-2.dot")
graph.write_png("gpt-2.png")

I get the error message: Expect '{' but got '['
So I modifid the function ggml_graph_dump_dot() in ggml.c like this:

void ggml_graph_dump_dot(const struct ggml_cgraph * gb, const struct ggml_cgraph * gf, const char * filename) {
    char color[16];

    FILE * fp = fopen(filename, "w");
    GGML_ASSERT(fp);

    fprintf(fp, "digraph G {\n");
    fprintf(fp, "  newrank = true;\n");
    fprintf(fp, "  rankdir = LR;\n");

    for (int i = 0; i < gb->n_nodes; i++) {
        struct ggml_tensor * node = gb->nodes[i];

        if (ggml_graph_get_parent(gb, node) != NULL) {
            continue;
        }

        if (node->is_param) {
            snprintf(color, sizeof(color), "yellow");
        } else if (node->grad) {
            if (ggml_graph_find(gf, node)) {
                snprintf(color, sizeof(color), "green");
            } else {
                snprintf(color, sizeof(color), "lightblue");
            }
        } else {
            snprintf(color, sizeof(color), "white");
        }

        fprintf(fp, "  \"%p\" { \
style = filled; fillcolor = %s; shape = record; \
label=\"%d [%d, %d] | <x>%s",
                (void *) node, color,
                i, node->ne[0], node->ne[1],
                GGML_OP_SYMBOL[node->op]);

        if (node->grad) {
            fprintf(fp, " | <g>%s\"; }\n", GGML_OP_SYMBOL[node->grad->op]);
        } else {
            fprintf(fp, "\"; }\n");
        }
    }

    for (int i = 0; i < gb->n_leafs; i++) {
        struct ggml_tensor * node = gb->leafs[i];

        snprintf(color, sizeof(color), "pink");

        if (ggml_nelements(node) == 1) {
            fprintf(fp, "  \"%p\" { \
style = filled; fillcolor = %s; shape = record; \
label=\"<x>%.1e\"; }\n",
                    (void *) node, color, ggml_get_f32_1d(node, 0));
        } else {
            fprintf(fp, "  \"%p\" { \
style = filled; fillcolor = %s; shape = record; \
label=\"<x>CONST %d [%d, %d]\"; }\n",
                    (void *) node, color,
                    i, node->ne[0], node->ne[1]);
        }
    }

    for (int i = 0; i < gb->n_nodes; i++) {
        struct ggml_tensor * node = gb->nodes[i];

        struct ggml_tensor * parent = ggml_graph_get_parent(gb, node);

        if (node->src0) {
            struct ggml_tensor * parent0 = ggml_graph_get_parent(gb, node->src0);

            fprintf(fp, "  \"%p\":%s -> \"%p\":%s { arrowhead = %s; style = %s; label = \"x\"; }\n",
                    parent0 ? (void *) parent0 : (void *) node->src0,
                    parent0 ? "g" : "x",
                    parent ? (void *) parent : (void *) node,
                    parent ? "g" : "x",
                    parent ? "empty" : "vee",
                    parent ? "dashed" : "solid");
        }

        if (node->src1) {
            struct ggml_tensor * parent1 = ggml_graph_get_parent(gb, node->src1);

            fprintf(fp, "  \"%p\":%s -> \"%p\":%s { arrowhead = %s; style = %s; label = \"y\"; }\n",
                    parent1 ? (void *) parent1 : (void *) node->src1,
                    parent1 ? "g" : "x",
                    parent ? (void *) parent : (void *) node,
                    parent ? "g" : "x",
                    parent ? "empty" : "vee",
                    parent ? "dashed" : "solid");
        }
    }

    for (int i = 0; i < gb->n_leafs; i++) {
        struct ggml_tensor * node = gb->leafs[i];

        if (node->src0) {
            fprintf(fp, "  \"%p\":%s -> \"%p\":%s [ label = \"x\"; ]\n",
                    (void *) node->src0, "x",
                    (void *) node, "x");
        }

        if (node->src1) {
            fprintf(fp, "  \"%p\":%s -> \"%p\":%s [ label = \"y\"; ]\n",
                    (void *) node->src1, "x",
                    (void *) node, "x");
        }
    }

    fprintf(fp, "}\n");

    fclose(fp);

    GGML_PRINT("%s: dot -Tpng %s -o %s.png && open %s.png\n", __func__, filename, filename, filename);
}

To replace the '[' and ] to '{' and '}'
Then it doesn't have new error , but the process blocked, can not stop.Blocked in here:
image

And I also run command in windows powershell, but it still blocked like this:
image

same in wsl:

image

So can anybody know what can I do? Thanks

Attach is the .dot file generated by me, you can modify the suffix from gpt-2.txt to gpt-2.dot. The model size is 7B-version.

gpt-2.txt

@ggerganov
Copy link
Member

The full network is too heavy to be plotted by graphviz.
You can easily plot just 1 layer - it's the same as the full network but without the n_layer repetition.

Simply apply this patch:

diff --git a/llama.cpp b/llama.cpp
index 2d02792..29928a0 100644
--- a/llama.cpp
+++ b/llama.cpp
@@ -863,7 +863,7 @@ static bool llama_eval_internal(
 
     struct ggml_tensor * inpL = ggml_get_rows(ctx0, model.tok_embeddings, embd);
 
-    for (int il = 0; il < n_layer; ++il) {
+    for (int il = 0; il < 1; ++il) {
         struct ggml_tensor * inpSA = inpL;
 
         struct ggml_tensor * cur;
@@ -1027,10 +1027,10 @@ static bool llama_eval_internal(
     ggml_build_forward_expand(&gf, inpL);
     ggml_graph_compute       (ctx0, &gf);
 
-    //if (n_past%100 == 0) {
-    //    ggml_graph_print   (&gf);
-    //    ggml_graph_dump_dot(&gf, NULL, "gpt-2.dot");
-    //}
+    if (n_past%100 == 0) {
+        ggml_graph_print   (&gf);
+        ggml_graph_dump_dot(&gf, NULL, "llama-1l.dot");
+    }
 
     //embd_w.resize(n_vocab*N);
     //memcpy(embd_w.data(), ggml_get_data(inpL), sizeof(float)*n_vocab*N);

Run the inference once and then generate a .png like this:

dot -Tpng llama-1l.dot -o llama-1l.dot.png

Here is the result:

llama-1l dot

@Alwaysion
Copy link
Author

Thx @ggerganov !
So do I need to modify the function ggml_graph_dump_dot() to replace the '[' to '}'?

@ggerganov
Copy link
Member

If you use the dot tool as I did - you don't need to modify it.

@Alwaysion
Copy link
Author

Thank you very much

If you use the dot tool as I did - you don't need to modify it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants