You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
A Python script to convert the output of NVIDIA Nsight Systems (in SQLite format) to JSON in [Google Chrome Trace Event Format](https://docs.google.com/document/d/1CvAClvFfyA5R-PhYUmn5OOQtYMH4h6I0nSsKchNAySU/preview#) for more customizable visualization and analysis. Inspired and adapted from [nvprof2json](https://github.com/ezyang/nvprof2json).
4
+
5
+
The SQLite schema used by Nsight Systems is documented [here](https://docs.nvidia.com/nsight-systems/UserGuide/index.html#exporter-sqlite-schema).
6
+
7
+
## Usage
8
+
*If you have a '.qdrep' file, you can convert it first to SQLite format through Nsight Systems [UI](https://developer.nvidia.com/nsight-systems/get-started) or [CLI](https://docs.nvidia.com/nsight-systems/UserGuide/index.html#cli-export-command-switch-options).*
9
+
10
+
To extract kernel activities and NVTX annotated regions (e.g. [torch.cuda.nvtx.range](https://pytorch.org/docs/stable/generated/torch.cuda.nvtx.range_push.html)):
For the list of available colors, see [here](https://chromium.googlesource.com/external/trace-viewer/+/bf55211014397cf0ebcd9e7090de1c4f84fc3ac0/tracing/tracing/ui/base/color_scheme.html).
34
+
35
+
## Known Issues
36
+
* This script assumes each process in the profile only executes kernel on one GPU. Process id is used to match NVTX regions to the corresponding device. Changes to process and thread naming scheme in the JSON file are needed if this assumption is violated.
start INTEGER NOT NULL, -- Event start timestamp (ns).
81
+
end INTEGER, -- Event end timestamp (ns).
82
+
eventType INTEGER NOT NULL, -- NVTX event type enum value. See docs for specifics.
83
+
rangeId INTEGER, -- Correlation ID returned from a nvtxRangeStart call.
84
+
category INTEGER, -- User-controlled ID that can be used to group events.
85
+
color INTEGER, -- Encoded ARGB color value.
86
+
text TEXT, -- Optional text message for non registered strings.
87
+
globalTid INTEGER, -- Serialized GlobalId.
88
+
endGlobalTid INTEGER, -- Serialized GlobalId. See docs for specifics.
89
+
textId INTEGER REFERENCES StringIds(id), -- StringId of the NVTX domain registered string.
90
+
domainId INTEGER, -- User-controlled ID that can be used to group events.
91
+
uint64Value INTEGER, -- One of possible payload value union members.
92
+
int64Value INTEGER, -- One of possible payload value union members.
93
+
doubleValue REAL, -- One of possible payload value union members.
94
+
uint32Value INTEGER, -- One of possible payload value union members.
95
+
int32Value INTEGER, -- One of possible payload value union members.
96
+
floatValue REAL, -- One of possible payload value union members.
97
+
jsonTextId INTEGER, -- One of possible payload value union members.
98
+
jsonText TEXT -- One of possible payload value union members.
99
+
100
+
NVTX_EVENT_TYPES
101
+
33 - NvtxCategory
102
+
34 - NvtxMark
103
+
39 - NvtxThread
104
+
59 - NvtxPushPopRange
105
+
60 - NvtxStartEndRange
106
+
75 - NvtxDomainCreate
107
+
76 - NvtxDomainDestroy
108
+
"""
109
+
# map each pid to a device. assumes each pid is associated with a single device
110
+
pid_to_device= {}
111
+
forrowinconn.execute("SELECT DISTINCT deviceId, globalPid / 0x1000000 % 0x1000000 AS PID FROM CUPTI_ACTIVITY_KIND_KERNEL"):
112
+
assertrow["PID"] notinpid_to_device, \
113
+
f"A single PID ({row['PID']}) is associated with multiple devices ({pid_to_device[row['PID']]} and {row['deviceId']})."
114
+
pid_to_device[row["PID"]] =row["deviceId"]
115
+
116
+
ifevent_prefixisNone:
117
+
match_text=''
118
+
else:
119
+
match_text=" AND "
120
+
iflen(event_prefix) ==1:
121
+
match_text+=f"NVTX_EVENTS.text LIKE '{event_prefix}%'"
122
+
else:
123
+
match_text+="("
124
+
foridx, prefixinenumerate(event_prefix):
125
+
match_text+=f"NVTX_EVENTS.text LIKE '{prefix}%'"
126
+
ifidx==len(event_prefix) -1:
127
+
match_text+=")"
128
+
else:
129
+
match_text+=" OR "
130
+
131
+
# eventType 59 is NvtxPushPopRange, which corresponds to torch.cuda.nvtx.range apis
132
+
forrowinconn.execute(f"SELECT start, end, text, globalTid / 0x1000000 % 0x1000000 AS PID, globalTid % 0x1000000 AS TID FROM NVTX_EVENTS WHERE NVTX_EVENTS.eventType == 59{match_text};"):
133
+
text=row['text']
134
+
pid=row['PID']
135
+
tid=row['TID']
136
+
assertpidinpid_to_device, f"PID {pid} not found in the pid to device map."
137
+
event= {
138
+
"name": text,
139
+
"ph": "X", # Complete Event (Begin + End event)
140
+
"cat": "nvtx",
141
+
"ts": munge_time(row["start"]),
142
+
"dur": munge_time(row["end"] -row["start"]),
143
+
"tid": "NVTX Thread {}".format(tid),
144
+
"pid": "Device {}".format(pid_to_device[pid]),
145
+
"args": {
146
+
# TODO: More
147
+
},
148
+
}
149
+
ifcolor_scheme:
150
+
forkey, colorincolor_scheme.items():
151
+
ifre.search(key, text):
152
+
event["cname"] =color
153
+
break
154
+
traceEvents.append(event)
155
+
156
+
defnsys2json():
157
+
conn=sqlite3.connect(args.filename)
158
+
conn.row_factory=sqlite3.Row
159
+
160
+
strings= {}
161
+
forrinconn.execute("SELECT id, value FROM StringIds"):
0 commit comments