Skip to content

negative memory increment #396

Description

@aidenhammond

I've seen similar tickets from 2018 on this topic, but I assume they've been fixed since. Getting a negative memory increment when running some code. Here is the code that I am running:

from torch import Tensor, linspace, meshgrid, zeros, square, div, sum, norm, sqrt, nan_to_num, nonzero, device, zeros_like, atan, cat, empty, subtract
import argparse
from torch.cuda import is_available
from torch.nn.functional import normalize
from scipy.constants import pi, epsilon_0
from math import ceil
from jaxtyping import Shaped
from matplotlib.pyplot import figure, show
from numpy import abs, min
import memory_profiler
#################################
# #
# Setup #
# #
#################################
# Checking for cuda-capable device (for gpu assistance)
device = device("cuda:0" if is_available() else "cpu")
# Parsing arguments
parser = argparse.ArgumentParser()
parser.add_argument('--charge', type=str, help='The name of the person.')
parser.add_argument('--side-length', type=float, help='The y-coordinate of observation.')
parser.add_argument('--x', type=float, help='The x-coordinate of observation.')
parser.add_argument('--y', type=float, help='The y-coordinate of observation.')
parser.add_argument('--z', type=float, help='The z-coordinate of observation.')
parser.add_argument('--n', type=float, help='The number of points.')
args = parser.parse_args() # get arguments
# set arguments to variables to save space
@profile
def main():
q = float(args.charge)
L = float(args.side_length)
x = float(args.x)
y = float(args.y)
z = float(args.z)
N = int(args.n)
sigma = q / L**2 # useful later
k= (q/N**2) / (4.0 * pi * epsilon_0)
_k = sigma / (pi*epsilon_0)
Ls = (L/2)**2
#### Preallocating tensors
# creating N number of points along z axis from 0 to z
z_coords = linspace(0, z, N, device=device)
_p = zeros(N, 1, 1, 3, device=device)
result = empty(N, 3)
estimated = empty(N,3)
# setting up tensor representing the square on the xy plane centered at the origin
# think of it like a cube of size 1*N*N where each point in that
# cube holds 3 values
# shape is [1,N,N,3]
t = zeros(1,N,N,3, device=device)
# Creating one-dim tensors of size N whose values are evenly spaced
# between -L/2 and L/2 for both x and y coordinates of charges # throughout a square plane centered at the origin
x_coords = linspace(-L/2.0, L/2.0, N) if N > 1 else Tensor([0.0])
y_coords = linspace(-L/2.0, L/2.0, N) if N > 1 else Tensor([0.0])
# putting those coordinates into a 2D grid
_x, _y = meshgrid(x_coords, y_coords)
# putting the grid in for the x and y components along the last
# dimension of our tensor that represents the square
t[:,:,:,0] = _x
t[:,:,:,1] = _y
# point of observation
# shape is [1,1,1,3]
p = Tensor([[[[x,y,z]]]], device=device)
# print to console
point = p[0][0][0]
p = p.subtract(t)
# basic efield equation
# 1 q
# E = ------ * ---- *r_hat
# 4pi*e0 r^2
print("E-Field at ", point," is: ", nan_to_num(sum((div(k, square(p)))*normalize(p,dim=3), dim=(1,2))))
#################################
# #
# Finding Percent Error #
# #
#################################
# reshaping and adding to tensor of correct shape
z_coords = z_coords.view(N, 1, 1)
_p[:,:,:,2] = z_coords
# finding estimated at the points along the z axis
estimated = nan_to_num(sum((div(k, square(_p-t)))*normalize(_p-t,dim=3), dim=(1,2)))
# finding actual
#
# sigma / (L/2)^2 \
# E = ------- * tan^-1 ( -------------------------- )
# pi*e0 \ z* sqrt(z^2 + 2*(L/2)^2) /
#
e = (_k) * atan(div(Ls,_p * sqrt(square(_p) + 2*Ls))) * normalize(_p, dim=3)
actual = nan_to_num(e.squeeze(1).squeeze(1))
#################################
# #
# Printing to console #
# #
#################################
z_coords = z_coords.squeeze(-1).squeeze(-1)
a = actual[:, 2].squeeze(-1).cpu().numpy()
e = estimated[:, 2].squeeze(-1).cpu().numpy()
print("Plotting....")
#
# Plotting
#
fig = figure()
ax1 = fig.add_subplot(1,2,1)
ax1.plot(z_coords.cpu().numpy(), a, label="Actual")
ax1.plot(z_coords.cpu().numpy(), e, label="Estimate")
ax2= fig.add_subplot(1,2,2)
ax2.plot(z_coords.cpu().numpy(), abs(e-a)/a, label="Percent Error")
show()
main()

This is how I am running it:

python -m memory_profiler efield.py --charge 0.1 --side-length 0.01 --x -1.694 --y -0.051 --z 2.345 --n 1001

This is the output I get:

E-Field at tensor([-1.6940, -0.0510, 2.3450]) is: tensor([[-1.8337e+08, -6.1105e+09, 1.3247e+08]])
Plotting....
efield.py:134: RuntimeWarning: invalid value encountered in divide
ax2.plot(z_coords.cpu().numpy(), abs(e-a)/a, label="Percent Error")
Filename: efield.py
Line # Mem usage Increment Occurrences Line Contents
=============================================================
34 207.062 MiB 207.062 MiB 1 @profile
35 def main():
36 207.062 MiB 0.000 MiB 1 q = float(args.charge)
37 207.062 MiB 0.000 MiB 1 L = float(args.side_length)
38 207.062 MiB 0.000 MiB 1 x = float(args.x)
39 207.062 MiB 0.000 MiB 1 y = float(args.y)
40 207.062 MiB 0.000 MiB 1 z = float(args.z)
41 207.062 MiB 0.000 MiB 1 N = int(args.n)
42 207.062 MiB 0.000 MiB 1 sigma = q / L**2 # useful later
43 207.062 MiB 0.000 MiB 1 k= (q/N**2) / (4.0 * pi * epsilon_0)
44 207.062 MiB 0.000 MiB 1 _k = sigma / (pi*epsilon_0)
45 207.062 MiB 0.000 MiB 1 Ls = (L/2)**2
46 47 #### Preallocating tensors
48 # creating N number of points along z axis from 0 to z
49 207.594 MiB 0.531 MiB 1 z_coords = linspace(0, z, N, device=device)
50 207.781 MiB 0.188 MiB 1 _p = zeros(N, 1, 1, 3, device=device)
51 207.797 MiB 0.016 MiB 1 result = empty(N, 3)
52 207.797 MiB 0.000 MiB 1 estimated = empty(N,3)
53 54 55 # setting up tensor representing the square on the xy plane centered at the origin
56 # think of it like a cube of size 1*N*N where each point in that
57 # cube holds 3 values
58 # shape is [1,N,N,3]
59 219.516 MiB 11.719 MiB 1 t = zeros(1,N,N,3, device=device)
60 61 # Creating one-dim tensors of size N whose values are evenly spaced
62 # between -L/2 and L/2 for both x and y coordinates of charges 63 # throughout a square plane centered at the origin
64 219.516 MiB 0.000 MiB 1 x_coords = linspace(-L/2.0, L/2.0, N) if N > 1 else Tensor([0.0])
65 219.516 MiB 0.000 MiB 1 y_coords = linspace(-L/2.0, L/2.0, N) if N > 1 else Tensor([0.0])
66 67 # putting those coordinates into a 2D grid
68 220.047 MiB 0.531 MiB 1 _x, _y = meshgrid(x_coords, y_coords)
69 70 # putting the grid in for the x and y components along the last
71 # dimension of our tensor that represents the square
72 220.547 MiB 0.500 MiB 1 t[:,:,:,0] = _x
73 220.547 MiB 0.000 MiB 1 t[:,:,:,1] = _y
74 75 # point of observation
76 # shape is [1,1,1,3]
77 220.656 MiB 0.109 MiB 1 p = Tensor([[[[x,y,z]]]], device=device)
78 79 # print to console
80 220.656 MiB 0.000 MiB 1 point = p[0][0][0]
81 232.281 MiB 11.625 MiB 1 p = p.subtract(t)
82 83 # basic efield equation
84 # 1 q
85 # E = ------ * ---- *r_hat
86 # 4pi*e0 r^2
87 276.828 MiB 44.547 MiB 1 print("E-Field at ", point," is: ", nan_to_num(sum((div(k, square(p)))*normalize(p,dim=3), dim=(1,2))))
88 89 #################################
90 # #
91 # Finding Percent Error #
92 # #
93 #################################
94 95 96 # reshaping and adding to tensor of correct shape
97 276.844 MiB 0.016 MiB 1 z_coords = z_coords.view(N, 1, 1)
98 276.844 MiB 0.000 MiB 1 _p[:,:,:,2] = z_coords
99 100 101 # finding estimated at the points along the z axis
102 53.266 MiB -223.578 MiB 1 estimated = nan_to_num(sum((div(k, square(_p-t)))*normalize(_p-t,dim=3), dim=(1,2)))
103 104 # finding actual
105 #
106 # sigma / (L/2)^2 \
107 # E = ------- * tan^-1 ( -------------------------- )
108 # pi*e0 \ z* sqrt(z^2 + 2*(L/2)^2) /
109 #
110 111 56.781 MiB 3.516 MiB 1 e = (_k) * atan(div(Ls,_p * sqrt(square(_p) + 2*Ls))) * normalize(_p, dim=3)
112 57.000 MiB 0.219 MiB 1 actual = nan_to_num(e.squeeze(1).squeeze(1))
113 114 #################################
115 # #
116 # Printing to console #
117 # #
118 #################################
119 57.094 MiB 0.094 MiB 1 z_coords = z_coords.squeeze(-1).squeeze(-1)
120 121 57.469 MiB 0.375 MiB 1 a = actual[:, 2].squeeze(-1).cpu().numpy()
122 57.469 MiB 0.000 MiB 1 e = estimated[:, 2].squeeze(-1).cpu().numpy()
123 124 57.609 MiB 0.141 MiB 1 print("Plotting....")
125 #
126 # Plotting
127 #
128 100.125 MiB 42.516 MiB 1 fig = figure()
129 108.234 MiB 8.109 MiB 1 ax1 = fig.add_subplot(1,2,1)
130 108.500 MiB 0.266 MiB 1 ax1.plot(z_coords.cpu().numpy(), a, label="Actual")
131 108.547 MiB 0.047 MiB 1 ax1.plot(z_coords.cpu().numpy(), e, label="Estimate")
132 133 108.953 MiB 0.406 MiB 1 ax2= fig.add_subplot(1,2,2)
134 109.344 MiB 0.391 MiB 1 ax2.plot(z_coords.cpu().numpy(), abs(e-a)/a, label="Percent Error")
135 136 172.156 MiB 62.812 MiB 1 show()

Line 102 has a memory increment of -223.578 MiB.

Here is an output of running uname -a on the M1 pro system:

Darwin MacBook-Pro.local 22.1.0 Darwin Kernel Version 22.1.0: Sun Oct 9 20:15:09 PDT 2022; root:xnu-8792.41.9~2/RELEASE_ARM64_T6000 arm64

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions