Skip to content
This repository was archived by the owner on Mar 21, 2024. It is now read-only.

Commit 06222aa

Browse files
committed
add gdb pretty-printer for thrust vectors
1 parent 583ab49 commit 06222aa

File tree

1 file changed

+119
-0
lines changed

1 file changed

+119
-0
lines changed

scripts/gdb-pretty-printers.py

+119
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
import gdb
2+
import sys
3+
4+
if sys.version_info[0] > 2:
5+
Iterator = object
6+
else:
7+
# "Polyfill" for Python2 Iterator interface
8+
class Iterator:
9+
def next(self):
10+
return self.__next__()
11+
12+
13+
class ThrustVectorPrinter(gdb.printing.PrettyPrinter):
14+
"Print a thrust::*_vector"
15+
16+
class _host_accessible_iterator(Iterator):
17+
def __init__(self, start, size):
18+
self.item = start
19+
self.size = size
20+
self.count = 0
21+
22+
def __iter__(self):
23+
return self
24+
25+
def __next__(self):
26+
if self.count >= self.size:
27+
raise StopIteration
28+
elt = self.item.dereference()
29+
count = self.count
30+
self.item = self.item + 1
31+
self.count = self.count + 1
32+
return ('[%d]' % count, elt)
33+
34+
class _device_iterator(Iterator):
35+
def __init__(self, start, size):
36+
self.exec = exec
37+
self.item = start
38+
self.size = size
39+
self.count = 0
40+
self.buffer = None
41+
self.sizeof = self.item.dereference().type.sizeof
42+
self.buffer_start = 0
43+
# At most 1 MB or size, at least 1
44+
self.buffer_size = min(size, max(1, 2 ** 20 // self.sizeof))
45+
self.buffer = gdb.parse_and_eval(
46+
'(void*)malloc(%s)' % (self.buffer_size * self.sizeof))
47+
self.buffer.fetch_lazy()
48+
self.buffer_count = self.buffer_size
49+
self.update_buffer()
50+
51+
def update_buffer(self):
52+
if self.buffer_count >= self.buffer_size:
53+
self.buffer_item = gdb.parse_and_eval(
54+
hex(self.buffer)).cast(self.item.type)
55+
self.buffer_count = 0
56+
self.buffer_start = self.count
57+
device_addr = hex(self.item.dereference().address)
58+
buffer_addr = hex(self.buffer)
59+
size = min(self.buffer_size, self.size -
60+
self.buffer_start) * self.sizeof
61+
status = gdb.parse_and_eval(
62+
'(cudaError)cudaMemcpy(%s, %s, %d, cudaMemcpyDeviceToHost)' % (buffer_addr, device_addr, size))
63+
if status != 0:
64+
raise gdb.MemoryError(
65+
'memcpy from device failed: %s' % status)
66+
67+
def __del__(self):
68+
gdb.parse_and_eval('(void)free(%s)' %
69+
hex(self.buffer)).fetch_lazy()
70+
71+
def __iter__(self):
72+
return self
73+
74+
def __next__(self):
75+
if self.count >= self.size:
76+
raise StopIteration
77+
self.update_buffer()
78+
elt = self.buffer_item.dereference()
79+
self.buffer_item = self.buffer_item + 1
80+
self.buffer_count = self.buffer_count + 1
81+
count = self.count
82+
self.item = self.item + 1
83+
self.count = self.count + 1
84+
return ('[%d]' % count, elt)
85+
86+
def __init__(self, val):
87+
self.val = val
88+
self.pointer = val['m_storage']['m_begin']['m_iterator']
89+
self.size = int(val['m_size'])
90+
self.capacity = int(val['m_storage']['m_size'])
91+
self.is_device = False
92+
if str(self.pointer.type).startswith("thrust::device_ptr"):
93+
self.pointer = self.pointer['m_iterator']
94+
self.is_device = True
95+
96+
def children(self):
97+
if self.is_device:
98+
return self._device_iterator(self.pointer, self.size)
99+
else:
100+
return self._host_accessible_iterator(self.pointer, self.size)
101+
102+
def to_string(self):
103+
typename = str(self.val.type)
104+
return ('%s of length %d, capacity %d' % (typename, self.size, self.capacity))
105+
106+
def display_hint(self):
107+
return 'array'
108+
109+
110+
def lookup_thrust_type(val):
111+
if not str(val.type.unqualified()).startswith('thrust::'):
112+
return None
113+
suffix = str(val.type.unqualified())[8:]
114+
if suffix.startswith('host_vector') or suffix.startswith('device_vector'):
115+
return ThrustVectorPrinter(val)
116+
return None
117+
118+
119+
gdb.pretty_printers.append(lookup_thrust_type)

0 commit comments

Comments
 (0)