muelea/selfcontact

SelfContactLoss - memory issues (running on GPU)

GuyTevet opened this issue · 3 comments

Hi Lea:)
Applying SelfContactLoss with default parameters on batch_size=32 (i.e. [32, 10475, 3] tensor for a smplx mesh), fails for trying to allocate 112GB of GPU memory. Is there a way to handle this?

RuntimeError: CUDA out of memory. Tried to allocate 112.33 GiB (GPU 0; 10.76 GiB total capacity; 309.89 MiB already allocated; 9.30 GiB free; 346.00 MiB reserved in total by PyTorch)

The memory issue occurs in the winding_numbers module:

Traceback (most recent call last):
  File "/disk2/guytevet/.pycharm_helpers/pydev/_pydevd_bundle/pydevd_exec2.py", line 3, in Exec
    exec(exp, global_vars, local_vars)
  File "<input>", line 1, in <module>
  File "/disk2/guytevet/venvs/py3.7_vibe/lib/python3.7/site-packages/torch/nn/modules/module.py", line 1051, in _call_impl
    return forward_call(*input, **kwargs)
  File "/disk2/guytevet/selfcontact/selfcontact/losses/general_selfcontact_loss.py", line 80, in forward
    test_segments=self.test_segments
  File "/disk2/guytevet/selfcontact/selfcontact/selfcontact.py", line 198, in segment_vertices
    test_segments
  File "/disk2/guytevet/selfcontact/selfcontact/selfcontact.py", line 136, in get_intersection_mask
    triangles).le(0.99)
  File "/disk2/guytevet/selfcontact/selfcontact/utils/mesh.py", line 224, in winding_numbers
    points, triangles, thresh=thresh).sum(dim=-1)
  File "/disk2/guytevet/selfcontact/selfcontact/utils/mesh.py", line 155, in solid_angles
    centered_tris = triangles[:, None] - points[:, :, None, None]
RuntimeError: CUDA out of memory. Tried to allocate 112.33 GiB (GPU 0; 10.76 GiB total capacity; 309.89 MiB already allocated; 9.30 GiB free; 346.00 MiB reserved in total by PyTorch)

Hi Guy,

the code was tested with 16 GB of RAM.

Since your RAM size is 12 GB, you can try to split the number of points to be tested into n chunks and do the intersection tests n times. This way the intersection tests will need less memory, but more time. The code block you want to change is here: https://github.com/muelea/selfcontact/blob/master/selfcontact/selfcontact.py#L135

For example, to replace two by four blocks, replace

# split because of memory into two chunks
exterior = torch.zeros((bs, nv), device=vertices.device,
    dtype=torch.bool)
exterior[:, :5000] = winding_numbers(vertices[:,:5000,:],
    triangles).le(0.99)
exterior[:, 5000:] = winding_numbers(vertices[:,5000:,:],
    triangles).le(0.99)

by

# split because of memory into four chunks
exterior = torch.zeros((bs, nv), device=vertices.device,
    dtype=torch.bool)
exterior[:, :3000] = winding_numbers(vertices[:,:3000,:],
    triangles).le(0.99)
exterior[:, 3000:6000] = winding_numbers(vertices[:,3000:6000,:],
    triangles).le(0.99)
exterior[:, 6000:9000] = winding_numbers(vertices[:,6000:9000,:],
    triangles).le(0.99)
exterior[:, 9000:] = winding_numbers(vertices[:,9000:,:],
    triangles).le(0.99)

If you use HD vertices, make the same changes here as well: https://github.com/muelea/selfcontact/blob/master/selfcontact/selfcontact.py#L161

Hope that helps,
Lea

Cool! Thanks:)