Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

make sample_point_in_half_sphere_shell more efficient #186

Conversation

soskek
Copy link
Contributor

@soskek soskek commented Mar 11, 2022

Thank you for your great work.

sample_point_in_half_sphere_shell function can be extremely slow if the region between inner_radius and outer_radius is narrow because many rejections happen. For example, if they are 0.99999 and 1.00001, it takes 0.44 sec/iter.

This PR implements a sampling function, which has the equivalent feature but is much faster (e.g., 0.000015 sec/iter in the same condition).
See https://math.stackexchange.com/questions/1111894/random-points-in-spherical-shell in detail of the algorithm.

METHOD   sec/iter 	                      inner_radius  outer_radius

CURRENT   6.361722946166992e-05 sec/iter for	 0.9 1.1
EFFICIENT 1.516876220703125e-05 sec/iter for	 0.9 1.1
CURRENT   0.0004531641721725464 sec/iter for	 0.99 1.01
EFFICIENT 1.4918088912963867e-05 sec/iter for	 0.99 1.01
CURRENT   0.004436958122253418 sec/iter for	 0.999 1.001
EFFICIENT 1.507430076599121e-05 sec/iter for	 0.999 1.001
CURRENT   0.04548759651184082 sec/iter for	 0.9999 1.0001
EFFICIENT 1.4777421951293946e-05 sec/iter for	 0.9999 1.0001
CURRENT   0.4282598567008972 sec/iter for	 0.99999 1.00001
EFFICIENT 1.5428066253662108e-05 sec/iter for	 0.99999 1.00001

profile snippet:

if __name__ == "__main__":
    import kubric as kb
    import numpy as np
    import time

    N = 10000
    def check_current_version(inner_radius, outer_radius):
        start = time.time()
        outs = []
        for frame in range(N):
            pos = kb.sample_point_in_half_sphere_shell(inner_radius, outer_radius, 0.0)
            outs.append(pos)
        print("CURRENT  ", (time.time() - start) / N, "sec/iter for\t", inner_radius, outer_radius)
        return np.array(outs)

    def check_efficient_version(inner_radius, outer_radius):
        start = time.time()
        outs = []
        for frame in range(N):
            pos = efficient__sample_point_in_half_sphere_shell(inner_radius, outer_radius, 0.0)
            outs.append(pos)
        print("EFFICIENT", (time.time() - start) / N, "sec/iter for\t", inner_radius, outer_radius)
        return np.array(outs)

    # check time
    check_current_version(inner_radius=0.9, outer_radius=1.1)
    check_efficient_version(inner_radius=0.9, outer_radius=1.1)
    check_current_version(inner_radius=0.99, outer_radius=1.01)
    check_efficient_version(inner_radius=0.99, outer_radius=1.01)
    check_current_version(inner_radius=0.999, outer_radius=1.001)
    check_efficient_version(inner_radius=0.999, outer_radius=1.001)
    check_current_version(inner_radius=0.9999, outer_radius=1.0001)
    check_efficient_version(inner_radius=0.9999, outer_radius=1.0001)
    check_current_version(inner_radius=0.99999, outer_radius=1.00001)
    check_efficient_version(inner_radius=0.99999, outer_radius=1.00001)

@soskek
Copy link
Contributor Author

soskek commented Mar 11, 2022

Visual comparison of samples from the current algorithm (red) and the new one (blue); they are matched.
20220311-202429

inner_radius=0.5, outer_radius=1.5

@taiya taiya requested a review from Qwlouse March 28, 2022 22:01
Copy link
Collaborator

@Qwlouse Qwlouse left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That looks great! Thanks for the upgrade.

@Qwlouse Qwlouse merged commit 2ad946d into google-research:main Apr 8, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

2 participants