Skip to content

ENH: compute mask only once per iteration in fractals notebook #103

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

Merged
merged 1 commit into from
Aug 23, 2021

Conversation

rossbar
Copy link
Collaborator

@rossbar rossbar commented Aug 15, 2021

Minor improvement to the fractals notebook. Modifies the functions so that the boolean mask representing non-diverged values is computed only once per iteration and is reused, which is more efficient.

In principle, this could be modified further to illustrate the use of out to save the allocation of a new array in each loop, e.g.

def divergence_rate(mesh, num_iter=10, radius=2):                               
                                                                                
    z = mesh.copy()                                                             
    diverge_len = np.zeros(mesh.shape)  # Keep tally of the number of iterations
    conv_mask = np.ones(mesh.shape, dtype=bool)
                                                                                
    # Iterate on element if and only if |element| < radius (Otherwise assume divergence)
    for i in range(num_iter):
        np.less(np.abs(z), radius, out=conv_mask)                         
        diverge_len[conv_mask] += 1                                             
        z[conv_mask] = f(z[conv_mask])                                          
                                                                                
    return diverge_len

However I don't think it's necessary for this case as this likely won't result in a significant speedup.

@MichaelRipa
Copy link
Contributor

I really like this add-on, I find it more readable having the mask creation and Boolean indexing separate, and I didn't realize that 3 identical Boolean masks were being created each iteration. Just out of curiosity, is the less method more efficient then doing

conv_mask &= np.abs(z) < radius

or is it just better for readability?

@rossbar
Copy link
Collaborator Author

rossbar commented Aug 23, 2021

The point of the less example in the OP was to illustrate the use of the out keyword to re-use the same memory at each iteration. You're right that the in-place operator should accomplish this as well, but note that the operations are not equivalent: conv_mask &= np.abs(z) < radius is equivalent to np.bitwise_and(conv_mask, np.abs(z) < 1, out=conv_mask).

@mattip mattip merged commit 1fecd19 into numpy:main Aug 23, 2021
@mattip
Copy link
Member

mattip commented Aug 23, 2021

Thanks @rossbar

@MichaelRipa
Copy link
Contributor

The point of the less example in the OP was to illustrate the use of the out keyword to re-use the same memory at each iteration. You're right that the in-place operator should accomplish this as well, but note that the operations are not equivalent: conv_mask &= np.abs(z) < radius is equivalent to np.bitwise_and(conv_mask, np.abs(z) < 1, out=conv_mask).

Ah that makes sense, thanks for clarifying!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants