Skip to content

Conversation

@fedetony
Copy link

@fedetony fedetony commented Jun 13, 2025

Optimization of ADC acquisition

NumPy is optimized for vectorized operations, which makes it significantly faster than Python loops. To improve the speed of your calculation, try using NumPy directly instead of list comprehensions.

This eliminates the loop altogether, allowing NumPy to perform element-wise operations efficiently. You should see a noticeable speed improvement, especially for large arrays.

We tested these with 250 Mega points and adquisition took 96.072 s using your code

bufferV = [(x * range) / maxADC.value for x in bufferADC]

by changing to:

bufferADC_np = np.array(bufferADC, dtype=np.int64)
bufferV = (bufferADC_np * range) / maxADC.value

took 1.347 s.
And if you premultiply the factor

normRange = range/maxADC.value
bufferV =  np.ctypeslib.as_array(bufferADC) * normRange

reduces to 1.022 s

Enjoy :)

Fixes #.

Changes proposed in this pull request:

  • Use numpy to deal with buffers
  • Use vectorial multiplication instead of for looping

significantly faster than Python loops. To improve the speed of your
calculation, try using NumPy directly instead of list comprehensions:
python

This eliminates the loop altogether, allowing NumPy to perform
element-wise operations efficiently. You should see a noticeable speed
improvement, especially for large arrays.

We tested these with 250 Mega points and adquisition took 96.072 s using
your code
```
normRange = range/maxADC.value
bufferV =  np.ctypeslib.as_array(bufferADC) * normRange
```
by changing to:
```
bufferADC_np = np.array(bufferADC, dtype=np.int64)
bufferV = (bufferADC_np * range) / maxADC.value
```
took 1.347 s.
And if you premultiply the factor
```
normRange = range/maxADC.value
bufferV =  np.ctypeslib.as_array(bufferADC) * normRange
```
reduces to 1.022 s

Enjoy :)
@fedetony
Copy link
Author

fedetony commented Jun 13, 2025

BTW

    # Splits out the individual bits from the port into the binary values for each digital channel/pin.
    for i in range(dataLength.value):
        for j in range(8):
            bufferBinaryDj[j][i] = 1 if (data[i] & (1 << (7-j))) else 0

    return bufferBinaryDj

Yes, you can speed up this operation significantly by using NumPy's bitwise operations and array broadcasting. Instead of looping through each element manually, try this approach:

data_np = np.array(data, dtype=np.uint8)
bufferBinaryDj = ((data_np[:, None] & (1 << np.arange(7, -1, -1))) > 0).astype(np.uint8).T

Why is this faster?

  • Vectorization: NumPy performs operations on entire arrays at once instead of iterating through elements in Python.
  • Broadcasting: You avoid explicit loops by leveraging NumPy’s ability to expand dimensions dynamically.
  • Optimized Memory Access: NumPy's implementation is built for efficient memory usage, reducing overhead compared to nested loops.

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.

1 participant