1 // =============================================================================
2 // === GPUQREngine/Source/GPUQREngine_GraphVisHelper.cpp =======================
3 // =============================================================================
4 // === This is used for development and debugging only. ========================
5 // =============================================================================
6 //
7 // This file contains logic to render the current state of the BucketList data
8 // structure, including the current arrangement of row tiles into column
9 // buckets and bundles. The output language is DOT for use with either
10 // GraphViz's dot or sfdp package.
11 //
12 // Bundles are colored by task type:
13 //   Apply         : Yellow
14 //   Factorize     : Red
15 //   ApplyFactorize: Orange
16 //
17 // =============================================================================
18 
19 #include "GPUQREngine_Internal.hpp"
20 
21 #ifdef GPUQRENGINE_RENDER
22 
23 #include "GPUQREngine_BucketList.hpp"
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 
28 void GraphVizHelper_ComputeBundleLabel
29 (
30     LLBundle& bundle,   // C++ Reference to the bundle
31     char *label         // (output) The label to use for the bundle
32 );
33 
34 static int DotSID = 1;
35 
GPUQREngine_RenderBuckets(BucketList * buckets)36 void GPUQREngine_RenderBuckets(BucketList *buckets)
37 {
38     // if(!RENDER_DENSE_FACTORIZATION) return;
39 
40     LLBundle *bundles = buckets->Bundles;
41 
42     int numBundles = buckets->numBundles;
43     char bundleNames[numBundles][64];
44     char bundleLabel[numBundles][64];
45 
46     Int *head = buckets->head;
47     Int *next = buckets->next;
48 
49     char filename[64];
50     sprintf(filename, "out_%d.dot", DotSID++);
51 
52     FILE *output = fopen(filename, "w");
53 
54     bool RenderOutline = false;
55     bool UseFancyRendering = false;
56 
57     /* If we want to render the outline, do it first. */
58     if (RenderOutline)
59     {
60         fprintf(output, "graph O\n");
61         fprintf(output, "{\n");
62         fprintf(output, "node [shape=circle, style=filled, color=black];\n");
63         for (int colBucket = 0; colBucket < buckets->numBuckets; colBucket++)
64         {
65             /* Shade the point depending on the region. */
66             const char *fillColor = "gray";
67             if (colBucket < buckets->Wavefront) fillColor = "green";
68             else if (colBucket <= buckets->LastBucket) fillColor = "red";
69             fprintf(output, "O_%d [fillcolor=%s];\n", colBucket, fillColor);
70         }
71         fprintf(output, "}\n");
72     }
73 
74     fprintf(output, "digraph D\n");
75     fprintf(output, "{\n");
76     fprintf(output, "node [shape=record, style=filled];\n");
77 
78     int start = (UseFancyRendering ? MAX(0, buckets->Wavefront - 1) : 0);
79     int end = (UseFancyRendering ?
80         MIN(buckets->numBuckets, buckets->LastBucket + 1)
81         : buckets->numBuckets);
82 
83     for (int colBucket = start; colBucket < end; colBucket++)
84     {
85 //      const char *colBucketName = "CB_" + colBucket;
86 //      const char *colBucketLabel = "ColBucket" + colBucket;
87             // +" (" + buckets->bundleCount[colBucket] + " bundles)";
88 //      const char *colBucketEmptyName = "CBE_" + colBucket;
89 //      const char *colBucketEmptyLabel = "Empty";
90         const char *wavefrontColor = (colBucket < buckets->Wavefront ?
91             "green" : "gray");
92 
93         fprintf(output, "CB_%d [label=\"ColBucket%d\", fillcolor=%s];\n",
94             colBucket, colBucket, wavefrontColor);
95         fprintf(output, "CBE_%d [label=\"Empty\"];\n", colBucket);
96 
97         /* Render the idle tiles. */
98         int node;
99         char lastTile[32]; strcpy(lastTile, "");
100         if ((node = head[colBucket]) != EMPTY)
101         {
102             sprintf(lastTile, "IdleTile_%d", node);
103 
104             const char *nodeShape = (buckets->triu[node] ?
105                 "triangle" : "ellipse");
106             fprintf(output,
107                 "IdleTile_%d [shape=%s, fillcolor=%s, label=\"%d\"];\n",
108                 node, nodeShape, wavefrontColor, node);
109             fprintf(output, "CB_%d -> IdleTile_%d;\n", colBucket, node);
110             int last = node;
111             while ((node = next[node]) != EMPTY)
112             {
113                 sprintf(lastTile, "IdleTile_%d", node);
114 
115                 nodeShape = (buckets->triu[node] ? "triangle" : "ellipse");
116                 fprintf(output, "IdleTile_%d [shape=%s, label=\"%d\"];\n",
117                     node, nodeShape, node);
118                 fprintf(output, "IdleTile_%d -> IdleTile_%d;\n", last, node);
119                 last = node;
120             }
121         }
122 
123         /* Now render the bundles native to this bucket. */
124 
125         /* Write the nodes */
126         int bbc = 0;
127         for(int i=0; i<numBundles; i++)
128         {
129             strcpy(bundleNames[i], "");
130             strcpy(bundleLabel[i], "");
131         }
132         for(int i=0; i<numBundles; i++)
133         {
134             LLBundle& bundle = bundles[i];
135             if (bundle.NativeBucket == colBucket)
136             {
137                 sprintf(bundleNames[bbc], "CB_%d_HB_%d", colBucket, bbc);
138 
139                 const char *taskColor = "white";
140                 bool isApply = (bundle.CurrentTask == TASKTYPE_GenericApply);
141                 bool isFactorize =
142                     (bundle.CurrentTask == TASKTYPE_GenericFactorize);
143                 taskColor =
144                     (isApply ? "yellow" : isFactorize ? "red" : "orange");
145 
146                 GraphVizHelper_ComputeBundleLabel(bundle, bundleLabel[bbc]);
147                 fprintf(output, "%s [fillcolor=\"%s\", label=\"%s\"];\n",
148                     bundleNames[bbc], taskColor, bundleLabel[bbc]);
149                 bbc++;
150             }
151         }
152 
153         /* Print connectivity. */
154         if (bbc > 0)
155         {
156             if(!strcmp(lastTile, ""))
157             {
158                 fprintf(output, "CB_%d -> %s;\n", colBucket, bundleNames[0]);
159             }
160             else
161             {
162                 fprintf(output, "%s -> %s;\n", lastTile, bundleNames[0]);
163             }
164 
165             for (int i = 1; i < bbc; i++)
166             {
167                 fprintf(output, "%s -> %s;\n",
168                     bundleNames[i-1], bundleNames[i]);
169             }
170             fprintf(output, "%s -> CBE_%d;\n", bundleNames[bbc-1], colBucket);
171         }
172         else if (head[colBucket] != EMPTY)
173         {
174             fprintf(output, "%s -> CBE_%d;\n", lastTile, colBucket);
175         }
176         else
177         {
178             fprintf(output, "CB_%d -> CBE_%d;\n", colBucket, colBucket);
179         }
180     }
181 
182     fprintf(output, "}\n");
183     fclose(output);
184 }
185 
GraphVizHelper_ComputeBundleLabel(LLBundle & bundle,char * label)186 void GraphVizHelper_ComputeBundleLabel
187 (
188     LLBundle& bundle,   // C++ Reference to the bundle
189     char *label         // (output) The label to use for the bundle
190 )
191 {
192     Int *next = bundle.Buckets->next;
193 
194     char temp[16];
195     strcpy(temp, "");
196 
197     strcpy(label, "");
198     if (bundle.Shadow != EMPTY)
199     {
200         sprintf(temp, "s%ld%s", bundle.Shadow,
201             (bundle.First != EMPTY ? "|" : ""));
202         strcat(label, temp);
203     }
204 
205     for (int i = bundle.First; i!=EMPTY; i=next[i])
206     {
207         sprintf(temp, "%d%s", i, (next[i] != EMPTY ? "|" : ""));
208         strcat(label, temp);
209     }
210     for (int i = bundle.Delta; i!=EMPTY; i=next[i])
211     {
212         sprintf(temp, "|%s%d", (i == bundle.Delta ? "D" : "d"), i);
213         strcat(label, temp);
214     }
215 }
216 #endif
217