C-Python 包装器中的内存泄漏
Memory leak in a C-Python wrapper
我有超过 100k 次迭代调用一个 C 函数,并且 运行 我看到每次调用该函数的探查器 +25 Mb。
结果不是累加的所以内存分配一定不能累加,否则就是内存泄漏(我每次调用一个文件后输出)。
我已经看到如何在 C 中释放变量,在 returning 之前使用 py_decref
。但就我而言,以及构建算法的方式,我没有 return 变量,但指针作为在每次迭代中 return 到 Python 代码中有用的参数。
以我的基本C语言知识,我尝试将参数转换为return值但没有成功。
这里是参数的声明和调用:
我的 C 库是 Illumination:
Illumination.restype = None
Illumination.argtypes = [ctypes.c_double, ctypes.c_double,
ndpointer(ctypes.c_float),
ndpointer(ctypes.c_int)]
照明中的所有中间变量都可以简单地使用free
释放。
C 中的函数是:
void Illumination(double Longitude, double Latitude, float *fact_sun, int *nb_nodes)
我已经玩过像 double 这样的 float 类型,希望以后的结果会更简洁,但它对内存泄漏没有帮助。
ctypes._reset_cache()
和 gc.collect()
通常在循环或脚本中的任何地方都没有帮助。
据我了解,我需要在 Python 中处理它。可惜我不知道怎么办。
分析结果为
Line # Mem usage Increment Occurences Line Contents
============================================================
30 106.109 MiB 106.109 MiB 1 @profile
31 def my_func():
32
33 # C Illumination function from shared file Illumination.so
34
35 106.242 MiB 0.133 MiB 1 lib = ctypes.CDLL('Illumination.so')
36 106.242 MiB 0.000 MiB 1 Illumination = lib.Illumination
37 106.242 MiB 0.000 MiB 1 Illumination.restype = None
38 106.242 MiB 0.000 MiB 1 Illumination.argtypes = [ctypes.c_double, ctypes.c_double,
39 106.242 MiB 0.000 MiB 1 ndpointer(ctypes.c_float),
40 106.242 MiB 0.000 MiB 1 ndpointer(ctypes.c_int)]
41
42 106.242 MiB 0.000 MiB 1 start_time = time.time()
43
44 # @profile
45 # #############################################################################################################
46 # variable initialization and declaration
47 # #############################################################################################################
48 # PATHNAMES
49
50 106.242 MiB 0.000 MiB 1 SHAPE_MODEL_PATHNAME = 'fac_ets.obj'
51 106.242 MiB 0.000 MiB 1 BARYCENTER_PATHNAME = 'bar_ycen.txt'
52 SS_COORD_PATHNAME = \
53 106.242 MiB 0.000 MiB 1 'SS_coord/sb_lonlat_ort.txt'
54
55 # 20201001174159.txt: Dt 3h old kernel | 20201014151855_1styear.txt: 25min
56 # 25_11_20.txt new kernel, dt=24,min
57 # lonlat_27_11_20_1ort_3h : Dt 3h new kernel
58
59 106.242 MiB 0.000 MiB 1 SH_FACET_PATHNAME = 'self_illu_facets/'
60
61 # facets_SH_geometry old folder
62
63 # facets_SH = pd.DataFrame(genfromtxt("facets_SH.txt"))[0].astype(np.int)
64
65 # SHAPE MODEL AND DX RESOLUTION
66
67 106.242 MiB 0.000 MiB 1 nb_face = 124938 # number of facets in shape model
68 106.242 MiB 0.000 MiB 1 nb_node = 62471 # number of nodes in shape model
69 106.242 MiB 0.000 MiB 1 nb_pts = 1 # & 18817 old kernel | 136346 & 18796 new kernel
70
71 # # LONGITUDE AND LATITUDE
72
73 115.289 MiB 9.047 MiB 1 lon_lat_dH = genfromtxt(SS_COORD_PATHNAME)
74 115.289 MiB 0.000 MiB 1 lon_lat_dH = pd.DataFrame(lon_lat_dH)
75
76 # if we read it from spice data file (ignore date and distance)
77
78 115.289 MiB 0.000 MiB 1 Longitude = lon_lat_dH[3]
79 115.883 MiB 0.594 MiB 1 Latitude = 90 - lon_lat_dH[4]
80 115.883 MiB 0.000 MiB 1 dH = lon_lat_dH[6] * 6.684587e-9 # 1.496e-8
81
82 # constants for energy equations
83
84 115.883 MiB 0.000 MiB 1 F = 1368 # constant
85 115.883 MiB 0.000 MiB 1 sigma = 5.67E-8 # stefan-boltzman constant
86 115.883 MiB 0.000 MiB 1 albedo = 0.06 # geometric albedo
87 115.883 MiB 0.000 MiB 1 albedo_bond = 0.04 # bond albedo
88 115.883 MiB 0.000 MiB 1 emiss = 0.95 # emissivity
89 115.883 MiB 0.000 MiB 1 inv_pi = 1 / pi
90 115.883 MiB 0.000 MiB 1 fact_SH_VIS = F * albedo * inv_pi
91 115.883 MiB 0.000 MiB 1 fact_T = (1 - albedo_bond) * F / (emiss * sigma)
92 115.883 MiB 0.000 MiB 1 fact_SH_IR = emiss * sigma * inv_pi
93
94 115.883 MiB 0.000 MiB 1 facets_selection = [44248] # 44247,44248
95
96 # 25821,119166-119167,35730-35731,43638,119147
97
98 179.820 MiB 0.000 MiB 2 for facet in facets_selection:
99
100 115.883 MiB 0.000 MiB 1 facet_i = facet
101 OUTPUT_PATHNAME = \
102 'flux_outputs/flux_new_kernel/region8' \
103 115.883 MiB 0.000 MiB 1 + str(facet_i) + 'testProfiler.txt'
104
105 # variables for illumination geometry
106
107 115.883 MiB 0.000 MiB 1 cos_Illumination = np.empty(nb_face, dtype=np.float32) # # float32 ## added
108 115.883 MiB 0.000 MiB 1 nb_node_Illumination = np.empty(nb_face, dtype=np.int32) # # int8 ## added
109
110 # variables for geometry of self-heating (cosz2)
111
112 116.387 MiB 0.504 MiB 1 cos_alpha = [None] * nb_face
113 117.418 MiB 1.031 MiB 1 angle_solid = [None] * nb_face
114 118.449 MiB 1.031 MiB 1 factor = [None] * nb_face
115
116 # #############################################################################################################
117 # SELF-HEATING GEOMETRY
118 # #############################################################################################################
119
120 # READING DATA OF SELF-HEATING GEOMETRY
121
122 127.465 MiB 9.016 MiB 1 Nod_coord = genfromtxt(SHAPE_MODEL_PATHNAME)
123 127.465 MiB 0.000 MiB 1 Nod_coord = pd.DataFrame(Nod_coord)
124 127.465 MiB 0.000 MiB 1 x_node = (Nod_coord[1])[0:nb_node].tolist()
125 127.465 MiB 0.000 MiB 1 y_node = (Nod_coord[2])[0:nb_node].tolist()
126 127.773 MiB 0.309 MiB 1 z_node = (Nod_coord[3])[0:nb_node].tolist()
127 127.773 MiB 0.000 MiB 1 i_f = np.asarray((Nod_coord[1])[nb_node:nb_face
128 128.801 MiB 1.027 MiB 1 + nb_node]).astype(int) - 1
129 128.801 MiB 0.000 MiB 1 j_f = np.asarray((Nod_coord[2])[nb_node:nb_face
130 129.840 MiB 1.039 MiB 1 + nb_node]).astype(int) - 1
131 129.840 MiB 0.000 MiB 1 k_f = np.asarray((Nod_coord[3])[nb_node:nb_face
132 130.871 MiB 1.031 MiB 1 + nb_node]).astype(int) - 1
133 130.871 MiB 0.000 MiB 1 m = [i_f[facet_i], j_f[facet_i], k_f[facet_i]]
134 130.871 MiB 0.000 MiB 1 node1 = np.array([x_node[m[0]], y_node[m[0]], z_node[m[0]]])
135 130.871 MiB 0.000 MiB 1 node2 = np.array([x_node[m[1]], y_node[m[1]], z_node[m[1]]])
136 130.871 MiB 0.000 MiB 1 node3 = np.array([x_node[m[2]], y_node[m[2]], z_node[m[2]]])
137 130.871 MiB 0.000 MiB 1 node1_node2 = np.array([node2[0] - node1[0], node2[1]
138 130.871 MiB 0.000 MiB 1 - node1[1], node2[2] - node1[2]])
139 130.871 MiB 0.000 MiB 1 node1_node3 = np.array([node3[0] - node1[0], node3[1]
140 130.871 MiB 0.000 MiB 1 - node1[1], node3[2] - node1[2]])
141
142 # READING FACETS BARYCENTER DATA
143
144 138.703 MiB 7.832 MiB 1 barycenter = genfromtxt(BARYCENTER_PATHNAME)
145 138.703 MiB 0.000 MiB 1 barycenter = pd.DataFrame(barycenter)
146 138.703 MiB 0.000 MiB 1 x_bary = barycenter[1]
147 138.703 MiB 0.000 MiB 1 y_bary = barycenter[2]
148 138.703 MiB 0.000 MiB 1 z_bary = barycenter[3]
149
150 # NORMAL VECTOR OF the FACET
151
152 138.703 MiB 0.000 MiB 1 vect_a = np.cross(node1_node2, node1_node3)
153
154 # SH = genfromtxt('output.txt')
155
156 138.703 MiB 0.000 MiB 1 SH = genfromtxt(glob.glob(SH_FACET_PATHNAME + '*'
157 143.492 MiB 4.789 MiB 1 + str(facet_i) + '.txt')[0])
158 143.492 MiB 0.000 MiB 1 SH = pd.DataFrame(SH)
159 143.492 MiB 0.000 MiB 1 S_facet = SH[0]
160 143.492 MiB 0.000 MiB 1 cos_SH = SH[1]
161 143.492 MiB 0.000 MiB 1 node_SH = SH[2]
162 143.492 MiB 0.000 MiB 1 x = SH[3]
163
164 # SOLID ANGLE
165
166 153.730 MiB 0.000 MiB 124939 for l in range(nb_face):
167 153.730 MiB 4.891 MiB 124938 if node_SH[l] != 3 or x[l] == 0:
168 153.730 MiB 0.000 MiB 124520 factor[l] = 0
169 else:
170
171 # vector facet->facet_x
172
173 153.730 MiB 4.867 MiB 418 vect_b = np.array([x_bary[l] - x_bary[facet_i],
174 153.730 MiB 0.000 MiB 418 y_bary[l] - y_bary[facet_i],
175 153.730 MiB 0.000 MiB 418 z_bary[l] - z_bary[facet_i]])
176 153.730 MiB 0.480 MiB 418 if np.linalg.norm(vect_b) == 0:
177 153.730 MiB 0.000 MiB 1 factor[l] = 0
178 else:
179 153.730 MiB 0.000 MiB 417 cos_alpha[l] = np.vdot(vect_a, vect_b) \
180 153.730 MiB 0.000 MiB 417 / (np.linalg.norm(vect_a)
181 153.730 MiB 0.000 MiB 417 * np.linalg.norm(vect_b))
182 153.730 MiB 0.000 MiB 417 if cos_alpha[l] <= 0:
183 factor[l] = 0
184 else:
185 factor[l] = cos_SH[l] * cos_alpha[l] \
186 153.730 MiB 0.000 MiB 417 * S_facet[l] / (np.linalg.norm(vect_b)
187 153.730 MiB 0.000 MiB 417 * np.linalg.norm(vect_b))
188 153.730 MiB 0.000 MiB 418 del vect_b # ###added
189 153.730 MiB 0.000 MiB 124938 ctypes._reset_cache()
190 # #############################################################################################################
191 # energy flux calculations
192 # #############################################################################################################
193
194 153.730 MiB 0.000 MiB 1 SH = 0
195 153.730 MiB 0.000 MiB 1 flux_neighbor_VIS = 0
196 153.730 MiB 0.000 MiB 1 flux_neighbor_IR = 0
197
198 # opening output file to write
199
200 153.730 MiB 0.000 MiB 1 file = open(OUTPUT_PATHNAME, 'w')
201
202 # file2 = open(OUTPUT_PATHNAME, 'w')
203
204 179.820 MiB 0.000 MiB 2 for i in range(nb_pts):
205
206 153.730 MiB 0.000 MiB 1 VIS = 0.0
207 153.730 MiB 0.000 MiB 1 IR = 0.0
208
209 153.730 MiB 0.000 MiB 1 inv_dH_sqr = 1 / (dH[i] * dH[i])
210
211 153.730 MiB 0.000 MiB 1 Illumination(Longitude[i], Latitude[i], cos_Illumination,
212 180.023 MiB 26.293 MiB 1 nb_node_Illumination)
213 180.023 MiB 0.000 MiB 1 if i % 1000 == 0:
214 179.820 MiB -0.203 MiB 1 gc.collect() # ##added
215 179.820 MiB 0.000 MiB 124939 for l in range(nb_face):
216 179.820 MiB 0.000 MiB 124938 if nb_node_Illumination[l] != 3 or cos_Illumination[l] \
217 179.820 MiB 0.000 MiB 42745 < 0:
218 179.820 MiB 0.000 MiB 82193 cos_Illumination[l] = 0
219
220 179.820 MiB 0.000 MiB 124938 if l == facet_i or factor[l] == 0:
221 179.820 MiB 0.000 MiB 124521 flux_neighbor_VIS = 0
222 179.820 MiB 0.000 MiB 124521 flux_neighbor_IR = 0
223 else:
224 flux_neighbor_VIS = cos_Illumination[l] * factor[l] \
225 179.820 MiB 0.000 MiB 417 * fact_SH_VIS * inv_dH_sqr
226 179.820 MiB 0.000 MiB 417 T_neighbor_4 = max(fact_T * cos_Illumination[l]
227 179.820 MiB 0.000 MiB 417 * inv_dH_sqr, 160000) # 30**4, 40k
228 flux_neighbor_IR = fact_SH_IR * factor[l] \
229 179.820 MiB 0.000 MiB 417 * T_neighbor_4
230
231 179.820 MiB 0.000 MiB 124938 VIS = VIS + flux_neighbor_VIS
232 179.820 MiB 0.000 MiB 124938 IR = IR + flux_neighbor_IR
233
234 179.820 MiB 0.000 MiB 1 Sol = cos_Illumination[facet_i] * F * inv_dH_sqr * (1
235 179.820 MiB 0.000 MiB 1 - albedo)
236 179.820 MiB 0.000 MiB 1 SH = (VIS + IR) * (1 - albedo)
237 179.820 MiB 0.000 MiB 1 Flux = Sol + SH
238 179.820 MiB 0.000 MiB 1 file.write(' %5.5f %5.5f %5.5f %5.5f %5.5f \n' % (Flux,
239 179.820 MiB 0.000 MiB 1 Sol, SH, VIS, IR))
240
241 # # geometry of illumination of facets contributing to selfheating of our facet
242 # for y in range(nb_facets_SH):
243 # file2.write(" %2.5f %2.5f \n" % (cos_Illumination[facets_SH[y]], nb_node_Illumination[facets_SH[y]]))
244
245 # file2.close()
246
247 179.820 MiB 0.000 MiB 1 file.close()
248 179.820 MiB 0.000 MiB 1 gc.collect()
249
250 179.820 MiB 0.000 MiB 1 cos_Illumination = None
251 179.820 MiB 0.000 MiB 1 del cos_Illumination
252 179.820 MiB 0.000 MiB 1 nb_node_Illumination = None
253 179.820 MiB 0.000 MiB 1 del nb_node_Illumination
254 179.820 MiB 0.000 MiB 1 interval = time.time() - start_time
255 179.820 MiB 0.000 MiB 1 print ('Total time in min:', interval / 60)
256 179.820 MiB 0.000 MiB 1 ctypes._reset_cache()
257 179.820 MiB 0.000 MiB 1 gc.collect()
有什么提示吗?
编辑:
代码
pastebin.com/N76eXu2w & pastebin.com/m2dT4CyQ
在您同时使用 Python 和 C++ 的情况下特别有用的工具是 https://github.com/vmware/chap,因为它理解 python 领域中的分配和使用 libc malloc 完成的分配.该工具是开源的,在 Linux.
上运行
对于你的情况,我会做的是:
来自 shell 提示:
echo 0x37 >/proc/<pid-of-your-process>/coredump_filter
使用 gcore 为您的进程收集核心。
等一分钟左右。
使用 gcore 为您的进程收集另一个核心。
在 chap 中打开每个核心并在 chap 命令提示符下执行以下操作:
redirect on
describe used
describe leaked
summarize used
如果您有实际泄漏,分配变得无法访问,“描述泄漏”的输出将反映这一点。
如果您只是容器增长,其中一些容器在不断增长,您应该能够通过比较这两种情况的“描述使用”的输出来很快地看到这一点。您可以识别出在第二个核心中出现得更多的某种对象,从中选择一个,然后在第二个核心上使用 chap 来了解它被保留的原因。
感谢您发布 pastebin links。我在那里看到您已经尝试将 Illumination()
函数更改为 return fact_sun
指针,而不是将其作为参数传递。我还看到您可能还添加了 free_mem()
函数。我会根据这个版本建议一个答案。
您的 python 代码中的 cos_Illumination
指针似乎正确使用了 free_mem()
函数。但是,您在 C 中实现 free_mem()
时似乎犯了一个小错误,这将产生很大的不同。在你的第二个 pastebin link 的第 576 行,它应该是 if (fact_sun)
而不是 if (!fact_sun)
。换句话说,如果指针有值(即它不是 NULL),而不是当它没有值时,你想释放内存。 (我假设你在 if
块内时没有看到 printf
语句的任何输出......无论如何这是不正确的,顺便说一下:它应该是 printf("%p\n", (void * )fact_sun);
没有 &
.)
请注意,严格来说,无论如何都不需要检查 free_mem()
中的 NULL,因为根据 C 标准,释放 NULL 指针应该是 nop。 (事实上,你的代码依赖于其他地方,因为它只分配和分配插槽 1
到 N_Node
和 N_Face
几个向量,但释放插槽 0
通过 N_Node
和 N_Face
。)但我个人认为检查它可能仍然是一个好主意,因为我已经看到 C 编译器的旧实例在释放 NULL 指针方面存在问题。
虽然将 fact_sun
设置为 NULL 也没有必要(因为 fact_sun
只是一个局部变量,因此当函数 returns 时超出范围),即对于在另一个 free_memory()
函数中释放的所有 global 变量,练习 会 是一个好主意。但是,就目前而言,这似乎不是代码问题的根源。
总的来说,它变成了:
// free memory of variable returned to python
void free_mem(double * fact_sun) {
if (fact_sun) {
printf("%p\n", (void * )fact_sun);
free(fact_sun);
}
}
最后,虽然这可能没什么大不了的(只要指针为 NULL),看起来你不需要第二个 pastebin link 的第 380 行的 free(nb_nodes)
(因为你永远不会分配它,除非有更多你没有包含的代码)。
我有超过 100k 次迭代调用一个 C 函数,并且 运行 我看到每次调用该函数的探查器 +25 Mb。
结果不是累加的所以内存分配一定不能累加,否则就是内存泄漏(我每次调用一个文件后输出)。
我已经看到如何在 C 中释放变量,在 returning 之前使用 py_decref
。但就我而言,以及构建算法的方式,我没有 return 变量,但指针作为在每次迭代中 return 到 Python 代码中有用的参数。
以我的基本C语言知识,我尝试将参数转换为return值但没有成功。
这里是参数的声明和调用:
我的 C 库是 Illumination:
Illumination.restype = None
Illumination.argtypes = [ctypes.c_double, ctypes.c_double,
ndpointer(ctypes.c_float),
ndpointer(ctypes.c_int)]
照明中的所有中间变量都可以简单地使用free
释放。
C 中的函数是:
void Illumination(double Longitude, double Latitude, float *fact_sun, int *nb_nodes)
我已经玩过像 double 这样的 float 类型,希望以后的结果会更简洁,但它对内存泄漏没有帮助。
ctypes._reset_cache()
和 gc.collect()
通常在循环或脚本中的任何地方都没有帮助。
据我了解,我需要在 Python 中处理它。可惜我不知道怎么办。
分析结果为
Line # Mem usage Increment Occurences Line Contents
============================================================
30 106.109 MiB 106.109 MiB 1 @profile
31 def my_func():
32
33 # C Illumination function from shared file Illumination.so
34
35 106.242 MiB 0.133 MiB 1 lib = ctypes.CDLL('Illumination.so')
36 106.242 MiB 0.000 MiB 1 Illumination = lib.Illumination
37 106.242 MiB 0.000 MiB 1 Illumination.restype = None
38 106.242 MiB 0.000 MiB 1 Illumination.argtypes = [ctypes.c_double, ctypes.c_double,
39 106.242 MiB 0.000 MiB 1 ndpointer(ctypes.c_float),
40 106.242 MiB 0.000 MiB 1 ndpointer(ctypes.c_int)]
41
42 106.242 MiB 0.000 MiB 1 start_time = time.time()
43
44 # @profile
45 # #############################################################################################################
46 # variable initialization and declaration
47 # #############################################################################################################
48 # PATHNAMES
49
50 106.242 MiB 0.000 MiB 1 SHAPE_MODEL_PATHNAME = 'fac_ets.obj'
51 106.242 MiB 0.000 MiB 1 BARYCENTER_PATHNAME = 'bar_ycen.txt'
52 SS_COORD_PATHNAME = \
53 106.242 MiB 0.000 MiB 1 'SS_coord/sb_lonlat_ort.txt'
54
55 # 20201001174159.txt: Dt 3h old kernel | 20201014151855_1styear.txt: 25min
56 # 25_11_20.txt new kernel, dt=24,min
57 # lonlat_27_11_20_1ort_3h : Dt 3h new kernel
58
59 106.242 MiB 0.000 MiB 1 SH_FACET_PATHNAME = 'self_illu_facets/'
60
61 # facets_SH_geometry old folder
62
63 # facets_SH = pd.DataFrame(genfromtxt("facets_SH.txt"))[0].astype(np.int)
64
65 # SHAPE MODEL AND DX RESOLUTION
66
67 106.242 MiB 0.000 MiB 1 nb_face = 124938 # number of facets in shape model
68 106.242 MiB 0.000 MiB 1 nb_node = 62471 # number of nodes in shape model
69 106.242 MiB 0.000 MiB 1 nb_pts = 1 # & 18817 old kernel | 136346 & 18796 new kernel
70
71 # # LONGITUDE AND LATITUDE
72
73 115.289 MiB 9.047 MiB 1 lon_lat_dH = genfromtxt(SS_COORD_PATHNAME)
74 115.289 MiB 0.000 MiB 1 lon_lat_dH = pd.DataFrame(lon_lat_dH)
75
76 # if we read it from spice data file (ignore date and distance)
77
78 115.289 MiB 0.000 MiB 1 Longitude = lon_lat_dH[3]
79 115.883 MiB 0.594 MiB 1 Latitude = 90 - lon_lat_dH[4]
80 115.883 MiB 0.000 MiB 1 dH = lon_lat_dH[6] * 6.684587e-9 # 1.496e-8
81
82 # constants for energy equations
83
84 115.883 MiB 0.000 MiB 1 F = 1368 # constant
85 115.883 MiB 0.000 MiB 1 sigma = 5.67E-8 # stefan-boltzman constant
86 115.883 MiB 0.000 MiB 1 albedo = 0.06 # geometric albedo
87 115.883 MiB 0.000 MiB 1 albedo_bond = 0.04 # bond albedo
88 115.883 MiB 0.000 MiB 1 emiss = 0.95 # emissivity
89 115.883 MiB 0.000 MiB 1 inv_pi = 1 / pi
90 115.883 MiB 0.000 MiB 1 fact_SH_VIS = F * albedo * inv_pi
91 115.883 MiB 0.000 MiB 1 fact_T = (1 - albedo_bond) * F / (emiss * sigma)
92 115.883 MiB 0.000 MiB 1 fact_SH_IR = emiss * sigma * inv_pi
93
94 115.883 MiB 0.000 MiB 1 facets_selection = [44248] # 44247,44248
95
96 # 25821,119166-119167,35730-35731,43638,119147
97
98 179.820 MiB 0.000 MiB 2 for facet in facets_selection:
99
100 115.883 MiB 0.000 MiB 1 facet_i = facet
101 OUTPUT_PATHNAME = \
102 'flux_outputs/flux_new_kernel/region8' \
103 115.883 MiB 0.000 MiB 1 + str(facet_i) + 'testProfiler.txt'
104
105 # variables for illumination geometry
106
107 115.883 MiB 0.000 MiB 1 cos_Illumination = np.empty(nb_face, dtype=np.float32) # # float32 ## added
108 115.883 MiB 0.000 MiB 1 nb_node_Illumination = np.empty(nb_face, dtype=np.int32) # # int8 ## added
109
110 # variables for geometry of self-heating (cosz2)
111
112 116.387 MiB 0.504 MiB 1 cos_alpha = [None] * nb_face
113 117.418 MiB 1.031 MiB 1 angle_solid = [None] * nb_face
114 118.449 MiB 1.031 MiB 1 factor = [None] * nb_face
115
116 # #############################################################################################################
117 # SELF-HEATING GEOMETRY
118 # #############################################################################################################
119
120 # READING DATA OF SELF-HEATING GEOMETRY
121
122 127.465 MiB 9.016 MiB 1 Nod_coord = genfromtxt(SHAPE_MODEL_PATHNAME)
123 127.465 MiB 0.000 MiB 1 Nod_coord = pd.DataFrame(Nod_coord)
124 127.465 MiB 0.000 MiB 1 x_node = (Nod_coord[1])[0:nb_node].tolist()
125 127.465 MiB 0.000 MiB 1 y_node = (Nod_coord[2])[0:nb_node].tolist()
126 127.773 MiB 0.309 MiB 1 z_node = (Nod_coord[3])[0:nb_node].tolist()
127 127.773 MiB 0.000 MiB 1 i_f = np.asarray((Nod_coord[1])[nb_node:nb_face
128 128.801 MiB 1.027 MiB 1 + nb_node]).astype(int) - 1
129 128.801 MiB 0.000 MiB 1 j_f = np.asarray((Nod_coord[2])[nb_node:nb_face
130 129.840 MiB 1.039 MiB 1 + nb_node]).astype(int) - 1
131 129.840 MiB 0.000 MiB 1 k_f = np.asarray((Nod_coord[3])[nb_node:nb_face
132 130.871 MiB 1.031 MiB 1 + nb_node]).astype(int) - 1
133 130.871 MiB 0.000 MiB 1 m = [i_f[facet_i], j_f[facet_i], k_f[facet_i]]
134 130.871 MiB 0.000 MiB 1 node1 = np.array([x_node[m[0]], y_node[m[0]], z_node[m[0]]])
135 130.871 MiB 0.000 MiB 1 node2 = np.array([x_node[m[1]], y_node[m[1]], z_node[m[1]]])
136 130.871 MiB 0.000 MiB 1 node3 = np.array([x_node[m[2]], y_node[m[2]], z_node[m[2]]])
137 130.871 MiB 0.000 MiB 1 node1_node2 = np.array([node2[0] - node1[0], node2[1]
138 130.871 MiB 0.000 MiB 1 - node1[1], node2[2] - node1[2]])
139 130.871 MiB 0.000 MiB 1 node1_node3 = np.array([node3[0] - node1[0], node3[1]
140 130.871 MiB 0.000 MiB 1 - node1[1], node3[2] - node1[2]])
141
142 # READING FACETS BARYCENTER DATA
143
144 138.703 MiB 7.832 MiB 1 barycenter = genfromtxt(BARYCENTER_PATHNAME)
145 138.703 MiB 0.000 MiB 1 barycenter = pd.DataFrame(barycenter)
146 138.703 MiB 0.000 MiB 1 x_bary = barycenter[1]
147 138.703 MiB 0.000 MiB 1 y_bary = barycenter[2]
148 138.703 MiB 0.000 MiB 1 z_bary = barycenter[3]
149
150 # NORMAL VECTOR OF the FACET
151
152 138.703 MiB 0.000 MiB 1 vect_a = np.cross(node1_node2, node1_node3)
153
154 # SH = genfromtxt('output.txt')
155
156 138.703 MiB 0.000 MiB 1 SH = genfromtxt(glob.glob(SH_FACET_PATHNAME + '*'
157 143.492 MiB 4.789 MiB 1 + str(facet_i) + '.txt')[0])
158 143.492 MiB 0.000 MiB 1 SH = pd.DataFrame(SH)
159 143.492 MiB 0.000 MiB 1 S_facet = SH[0]
160 143.492 MiB 0.000 MiB 1 cos_SH = SH[1]
161 143.492 MiB 0.000 MiB 1 node_SH = SH[2]
162 143.492 MiB 0.000 MiB 1 x = SH[3]
163
164 # SOLID ANGLE
165
166 153.730 MiB 0.000 MiB 124939 for l in range(nb_face):
167 153.730 MiB 4.891 MiB 124938 if node_SH[l] != 3 or x[l] == 0:
168 153.730 MiB 0.000 MiB 124520 factor[l] = 0
169 else:
170
171 # vector facet->facet_x
172
173 153.730 MiB 4.867 MiB 418 vect_b = np.array([x_bary[l] - x_bary[facet_i],
174 153.730 MiB 0.000 MiB 418 y_bary[l] - y_bary[facet_i],
175 153.730 MiB 0.000 MiB 418 z_bary[l] - z_bary[facet_i]])
176 153.730 MiB 0.480 MiB 418 if np.linalg.norm(vect_b) == 0:
177 153.730 MiB 0.000 MiB 1 factor[l] = 0
178 else:
179 153.730 MiB 0.000 MiB 417 cos_alpha[l] = np.vdot(vect_a, vect_b) \
180 153.730 MiB 0.000 MiB 417 / (np.linalg.norm(vect_a)
181 153.730 MiB 0.000 MiB 417 * np.linalg.norm(vect_b))
182 153.730 MiB 0.000 MiB 417 if cos_alpha[l] <= 0:
183 factor[l] = 0
184 else:
185 factor[l] = cos_SH[l] * cos_alpha[l] \
186 153.730 MiB 0.000 MiB 417 * S_facet[l] / (np.linalg.norm(vect_b)
187 153.730 MiB 0.000 MiB 417 * np.linalg.norm(vect_b))
188 153.730 MiB 0.000 MiB 418 del vect_b # ###added
189 153.730 MiB 0.000 MiB 124938 ctypes._reset_cache()
190 # #############################################################################################################
191 # energy flux calculations
192 # #############################################################################################################
193
194 153.730 MiB 0.000 MiB 1 SH = 0
195 153.730 MiB 0.000 MiB 1 flux_neighbor_VIS = 0
196 153.730 MiB 0.000 MiB 1 flux_neighbor_IR = 0
197
198 # opening output file to write
199
200 153.730 MiB 0.000 MiB 1 file = open(OUTPUT_PATHNAME, 'w')
201
202 # file2 = open(OUTPUT_PATHNAME, 'w')
203
204 179.820 MiB 0.000 MiB 2 for i in range(nb_pts):
205
206 153.730 MiB 0.000 MiB 1 VIS = 0.0
207 153.730 MiB 0.000 MiB 1 IR = 0.0
208
209 153.730 MiB 0.000 MiB 1 inv_dH_sqr = 1 / (dH[i] * dH[i])
210
211 153.730 MiB 0.000 MiB 1 Illumination(Longitude[i], Latitude[i], cos_Illumination,
212 180.023 MiB 26.293 MiB 1 nb_node_Illumination)
213 180.023 MiB 0.000 MiB 1 if i % 1000 == 0:
214 179.820 MiB -0.203 MiB 1 gc.collect() # ##added
215 179.820 MiB 0.000 MiB 124939 for l in range(nb_face):
216 179.820 MiB 0.000 MiB 124938 if nb_node_Illumination[l] != 3 or cos_Illumination[l] \
217 179.820 MiB 0.000 MiB 42745 < 0:
218 179.820 MiB 0.000 MiB 82193 cos_Illumination[l] = 0
219
220 179.820 MiB 0.000 MiB 124938 if l == facet_i or factor[l] == 0:
221 179.820 MiB 0.000 MiB 124521 flux_neighbor_VIS = 0
222 179.820 MiB 0.000 MiB 124521 flux_neighbor_IR = 0
223 else:
224 flux_neighbor_VIS = cos_Illumination[l] * factor[l] \
225 179.820 MiB 0.000 MiB 417 * fact_SH_VIS * inv_dH_sqr
226 179.820 MiB 0.000 MiB 417 T_neighbor_4 = max(fact_T * cos_Illumination[l]
227 179.820 MiB 0.000 MiB 417 * inv_dH_sqr, 160000) # 30**4, 40k
228 flux_neighbor_IR = fact_SH_IR * factor[l] \
229 179.820 MiB 0.000 MiB 417 * T_neighbor_4
230
231 179.820 MiB 0.000 MiB 124938 VIS = VIS + flux_neighbor_VIS
232 179.820 MiB 0.000 MiB 124938 IR = IR + flux_neighbor_IR
233
234 179.820 MiB 0.000 MiB 1 Sol = cos_Illumination[facet_i] * F * inv_dH_sqr * (1
235 179.820 MiB 0.000 MiB 1 - albedo)
236 179.820 MiB 0.000 MiB 1 SH = (VIS + IR) * (1 - albedo)
237 179.820 MiB 0.000 MiB 1 Flux = Sol + SH
238 179.820 MiB 0.000 MiB 1 file.write(' %5.5f %5.5f %5.5f %5.5f %5.5f \n' % (Flux,
239 179.820 MiB 0.000 MiB 1 Sol, SH, VIS, IR))
240
241 # # geometry of illumination of facets contributing to selfheating of our facet
242 # for y in range(nb_facets_SH):
243 # file2.write(" %2.5f %2.5f \n" % (cos_Illumination[facets_SH[y]], nb_node_Illumination[facets_SH[y]]))
244
245 # file2.close()
246
247 179.820 MiB 0.000 MiB 1 file.close()
248 179.820 MiB 0.000 MiB 1 gc.collect()
249
250 179.820 MiB 0.000 MiB 1 cos_Illumination = None
251 179.820 MiB 0.000 MiB 1 del cos_Illumination
252 179.820 MiB 0.000 MiB 1 nb_node_Illumination = None
253 179.820 MiB 0.000 MiB 1 del nb_node_Illumination
254 179.820 MiB 0.000 MiB 1 interval = time.time() - start_time
255 179.820 MiB 0.000 MiB 1 print ('Total time in min:', interval / 60)
256 179.820 MiB 0.000 MiB 1 ctypes._reset_cache()
257 179.820 MiB 0.000 MiB 1 gc.collect()
有什么提示吗?
编辑: 代码 pastebin.com/N76eXu2w & pastebin.com/m2dT4CyQ
在您同时使用 Python 和 C++ 的情况下特别有用的工具是 https://github.com/vmware/chap,因为它理解 python 领域中的分配和使用 libc malloc 完成的分配.该工具是开源的,在 Linux.
上运行对于你的情况,我会做的是:
来自 shell 提示:
echo 0x37 >/proc/<pid-of-your-process>/coredump_filter
使用 gcore 为您的进程收集核心。
等一分钟左右。
使用 gcore 为您的进程收集另一个核心。
在 chap 中打开每个核心并在 chap 命令提示符下执行以下操作:
redirect on
describe used
describe leaked
summarize used
如果您有实际泄漏,分配变得无法访问,“描述泄漏”的输出将反映这一点。
如果您只是容器增长,其中一些容器在不断增长,您应该能够通过比较这两种情况的“描述使用”的输出来很快地看到这一点。您可以识别出在第二个核心中出现得更多的某种对象,从中选择一个,然后在第二个核心上使用 chap 来了解它被保留的原因。
感谢您发布 pastebin links。我在那里看到您已经尝试将 Illumination()
函数更改为 return fact_sun
指针,而不是将其作为参数传递。我还看到您可能还添加了 free_mem()
函数。我会根据这个版本建议一个答案。
您的 python 代码中的 cos_Illumination
指针似乎正确使用了 free_mem()
函数。但是,您在 C 中实现 free_mem()
时似乎犯了一个小错误,这将产生很大的不同。在你的第二个 pastebin link 的第 576 行,它应该是 if (fact_sun)
而不是 if (!fact_sun)
。换句话说,如果指针有值(即它不是 NULL),而不是当它没有值时,你想释放内存。 (我假设你在 if
块内时没有看到 printf
语句的任何输出......无论如何这是不正确的,顺便说一下:它应该是 printf("%p\n", (void * )fact_sun);
没有 &
.)
请注意,严格来说,无论如何都不需要检查 free_mem()
中的 NULL,因为根据 C 标准,释放 NULL 指针应该是 nop。 (事实上,你的代码依赖于其他地方,因为它只分配和分配插槽 1
到 N_Node
和 N_Face
几个向量,但释放插槽 0
通过 N_Node
和 N_Face
。)但我个人认为检查它可能仍然是一个好主意,因为我已经看到 C 编译器的旧实例在释放 NULL 指针方面存在问题。
虽然将 fact_sun
设置为 NULL 也没有必要(因为 fact_sun
只是一个局部变量,因此当函数 returns 时超出范围),即对于在另一个 free_memory()
函数中释放的所有 global 变量,练习 会 是一个好主意。但是,就目前而言,这似乎不是代码问题的根源。
总的来说,它变成了:
// free memory of variable returned to python
void free_mem(double * fact_sun) {
if (fact_sun) {
printf("%p\n", (void * )fact_sun);
free(fact_sun);
}
}
最后,虽然这可能没什么大不了的(只要指针为 NULL),看起来你不需要第二个 pastebin link 的第 380 行的 free(nb_nodes)
(因为你永远不会分配它,除非有更多你没有包含的代码)。