<div dir="ltr">Thank you Sebastian and Andras for your detailed replies.<div><br></div><div>Sebastian, your suggestion of adding `item.item()` solved my problem! Now the for loop is still slower than vectorize, but by a smaller factor, and that's fast enough for my demonstration. My problem is solved and I'm very happy!</div><div><br></div><div>I also tried your `out=` suggestion for vectorize, but I think you made a mistake, as it doesn't seem that it takes that argument. If I missed something and it does (maybe it's a very new feature?) that would be even better for me than the `.item()` solution.</div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Sun, Jul 12, 2020 at 5:03 PM Sebastian Berg <<a href="mailto:sebastian@sipsolutions.net">sebastian@sipsolutions.net</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">On Sun, 2020-07-12 at 16:00 +0300, Ram Rachum wrote:<br>
> Hi everyone,<br>
> <br>
> Here's a problem I've been dealing with. I wonder whether NumPy has a<br>
> tool<br>
> that will help me, or whether this could be a useful feature request.<br>
> <br>
> In the upcoming EuroPython 20200, I'll do a talk about live-coding a<br>
> music<br>
> synthesizer. It's going to be a fun talk, I'll use the sounddevice<br>
> <<a href="https://github.com/spatialaudio/python-sounddevice/" rel="noreferrer" target="_blank">https://github.com/spatialaudio/python-sounddevice/</a>> module to make<br>
> a<br>
> program that plays music. Do attend, or watch it on YouTube when it's<br>
> out :)<br>
> <br>
<br>
Sounds like a fun talk :).<br>
<br>
> There's a part in my talk that I could make simpler, and thus shave<br>
> 3-4<br>
> minutes of cumbersome explanations. These 3-4 minutes matter a great<br>
> deal<br>
> to me. But for that I need to do something with NumPy and I don't<br>
> know<br>
> whether it's possible or not.<br>
> <br>
> <br>
> The sounddevice library takes an ndarray of sound data and plays it.<br>
> Currently I use `vectorize` to produce that array:<br>
> <br>
>     output_array = np.vectorize(f, otypes='d')(input_array)<br>
> <br>
> And I'd like to replace it with this code, which is supposed to give<br>
> the<br>
> same output:<br>
> <br>
>     output_array = np.ndarray(input_array.shape, dtype='d')<br>
<br>
Maybe use `np.empty(inpyt_array.shape, dtype="d")` instead.<br>
`np.ndarray` works but is pretty low-level, and I would usually avoid<br>
it for array creation.<br>
<br>
>     for i, item in enumerate(input_array):<br>
>         output_array[i] = f(item)<br>
> <br>
<br>
Ok, one hack that you can try, is to replace `item` with `item.item()`,<br>
that will convert the NumPy scalar to a Python scalar, which is quite a<br>
lot more lightweight and faster.  Also it might give PyPy more chance<br>
to optimize `f` I suppose.<br>
<br>
<br>
> The reason I want the second version is that I can then have<br>
> sounddevice<br>
> start playing `output_array` in a separate thread, while it's being<br>
> calculated. (Yes, I know about the GIL, I believe that sounddevice<br>
> releases<br>
> it.)<br>
<br>
`np.vectorize` will definitely not release the GIL, this loop may in<br>
between (I am not sure), but also adds quite a bit of overheads<br>
compared to `vectorize`.  The best thing of course would be if you can<br>
rewrite `f` to accept an array?<br>
<br>
<br>
> Unfortunately, the for loop is very slow, even when I'm not<br>
> processing the<br>
> data on separate thread. I benchmarked it on both CPython and PyPy3,<br>
> which<br>
> is my target platform. On CPython it's 3 times slower than vectorize,<br>
> and<br>
> on PyPy3 it's 67 times slower than vectorize! That's despite the fact<br>
> that<br>
> the Numpy documentation says "The `vectorize` function is provided<br>
> primarily for convenience, not for performance. The implementation is<br>
> essentially a `for` loop."<br>
<br>
PyPy is nice because it makes NumPy just work. Unfortunately, that also<br>
adds some overheads, so at least some slowdown is probably expected.  I<br>
am not sure about why it is so much.<br>
I would not be surprised if a list comprehension is not much faster,<br>
especially on PyPy (assuming you cannot modify `f` to work with<br>
arrays).<br>
<br>
> So here are a few questions:<br>
> <br>
> 1. Is there something like `vectorize`, except you get to access the<br>
> output<br>
> array before it's finished? If not, what do you think about adding<br>
> that as<br>
> an option to `vectorize`?<br>
<br>
vectorize should allow an `out=` argument to pass in the output array,<br>
would that help you?  So you can access it, but I am not sure how that<br>
will help you.  Although you could create a big result array and then<br>
access chunks of it:<br>
<br>
   final_arr = np.empty(...)<br>
   newly_written = slice(0, 1000)<br>
   run_calculation(final_arr[newly_written])<br>
<br>
where newly_written is defined by the input chunk you got, I suppose.<br>
<br>
<br>
> <br>
> 2. Is there a more efficient way of writing the `for` loop I've<br>
> written<br>
> above? Or any other kind of solution to my <br>
<br>
As said, the main thing would be to modify `f` in whatever way<br>
possible.  For that it would be useful to know what `f` does exactly.<br>
Maybe you can move `f` to Cython or numba, or maybe write in a way that<br>
works on arrays...<br>
<br>
> <br>
> Thanks for your help,<br>
> Ram Rachum.<br>
> _______________________________________________<br>
> NumPy-Discussion mailing list<br>
> <a href="mailto:NumPy-Discussion@python.org" target="_blank">NumPy-Discussion@python.org</a><br>
> <a href="https://mail.python.org/mailman/listinfo/numpy-discussion" rel="noreferrer" target="_blank">https://mail.python.org/mailman/listinfo/numpy-discussion</a><br>
<br>
_______________________________________________<br>
NumPy-Discussion mailing list<br>
<a href="mailto:NumPy-Discussion@python.org" target="_blank">NumPy-Discussion@python.org</a><br>
<a href="https://mail.python.org/mailman/listinfo/numpy-discussion" rel="noreferrer" target="_blank">https://mail.python.org/mailman/listinfo/numpy-discussion</a><br>
</blockquote></div>