#๐Ÿ”’ Help with optimizing string art program

5 messages ยท Page 1 of 1 (latest)

blissful flume
#

Here is my code

I am trying to make a program that approximates an image by wrapping "string" around "nails" that are around the edge of the circle.

The basic flow of my code is as follows:

  • Load the image and split it into CMYK
  • Generate a 3d tensor where each 2d slice is a possible line that can be drawn between the current "nail" and all other nails (including itself)
  • Find the slice with the lowese summed square error when added to the current string art and compared with the real image
  • Repeat until all possible lines you can draw have worse/the same summed square error as the current string art
  • Repeat for each color channel

This works really well for very small images (100x100 to 250x250) and I can use up to like almost 2000 "nails" and have it run really quick. It does start to get really slow really fast, and I get a CUDA timeout error on around 800x800 and anything around 1000x1000 I just get a GPU memory error. The timeout error had some advice on solving it, but I don't know what that actually does/means and I would rather fix any issues with allocating more memory than necessary in my code first. (I am using a GTX 980 which is almost 10 years old and only has 4GB of VRAM, so I would assume on a more modern GPU with more VRAM, it would be able to handle larger images before running into the CUDA launch error and GPU memory error)

RuntimeError: CUDA error: the launch timed out and was terminated
CUDA kernel errors might be asynchronously reported at some other API call, so the stacktrace below might be incorrect.
For debugging consider passing CUDA_LAUNCH_BLOCKING=1.
Compile with TORCH_USE_CUDA_DSA to enable device-side assertions.

continued in next message...

drifting stumpBOT
#

@blissful flume

Python help channel opened

Remember to:

  • Ask your Python question, not if you can ask or if there's an expert who can help.
  • Show a code sample as text (rather than a screenshot) and the error message, if you've got one.
  • Explain what you expect to happen and what actually happens.

:warning: Do not pip install anything that isn't related to your question, especially if asked to over DMs.

blissful flume
#

...continued

I am fairly certain the calculate_lines() and bulk_square_error() methods can be improved a lot.

calculate_lines() takes in a parent image of type ImageTensor which is just my subclass of torch.Tensor, the current points of type torch.Tensor and of the form [y, x], and then the list of all points to draw to of type torch.Tensor of the form [[y_0, x_0], [y_1, x_1], ...] and returns a torch.Tensor of the form [y, x, point_being_drawn_to]. I am pretty sure that the biggest bottleneck of this function is the creation of y0, x0, y1, x1, delta_y, and delta_x. I am sure there is a better way to be able to handle them than what I am doing, which is just expanding them to be the desired output shape. but I am sure that allocates a lot more memory than is necessary and that there is a better way to handle that, but I am very new to using pytorch and am not very familiar with all of its methods. I am using this formula to draw the lines.

bulk_square_error() takes in a 3d tensor of each of the lines added to the current string art and the 2d real target image and returns a 1d tensor of the sumemd square error of each 2d slice. This function has the same problem as calculate_lines() where I am expanding the target image to be the same shape as the 3d tensor. I am sure there is a way to compare each slice to the same 2d tensor without having to expand it to take up more memory.

I am looking for any any ways to improve the speed/GPU memory usage of my program, and any criticisms/feedback regarding code style or my aproach to the problem.

Any help is appreciated. Thanks!

The distance (or perpendicular distance) from a point to a line is the shortest distance from a fixed point to any point on a fixed infinite line in Euclidean geometry. It is the length of the line segment which joins the point to the line and is perpendicular to the line. The formula for calculating it can be derived and expressed in several wa...

drifting stumpBOT
#

@blissful flume

Python help channel closed

This help channel has been closed and it's no longer possible to send messages here. If your question wasn't answered, feel free to create a new post in #1035199133436354600. To maximize your chances of getting a response, check out this guide on asking good questions.