jonasdedden commented on PR #51611:
URL: https://github.com/apache/arrow/pull/51611#issuecomment-5906505525

   972bc4c speeds up the per-list scan: short lists are now 2.4–4.1× faster, 
long lists are unchanged. The scan used to build an 
`OptionalBinaryBitBlockCounter` per list. Now it folds validity into the match 
bitmap once, reads a single unaligned word for lists spanning ≤ 64 bits, and 
looks up the offsets/sizes/width once per batch.        
   
   | List length | Match rate | `equal` alone | `list_contains` before 
(95d6b87) | `list_contains` after (972bc4c) | Speedup |
   |---:|---:|---:|---:|---:|---:|                                              
               
   | 1 | 1e-5 | 18 ms | 346 ms | 108 ms | 3.2× |
   | 3 | 1e-5 | 19 ms | 140 ms | 48 ms | 2.9× |
   | 3 | 30% | 19 ms | 196 ms | 48 ms | 4.1× |
   | 10 | 30% | 19 ms | 68 ms | 28 ms | 2.4× |
   | 100 | 30% | 18 ms | 26 ms | 26 ms | 1.0× |
   | 1,000 | 1e-5 | 19 ms | 21 ms | 20 ms | 1.0× |
   | 1,000 | 30% | 18 ms | 19 ms | 19 ms | 1.0× |                    
   
   <details>                                                                    
                    
   <summary>Setup and script</summary>
   
   50M `int64` values in one `list<int64>` array, `int64` item, best of 7, best 
of two runs per build (runs differed by ≤ 6 ms). Release build, 8 cores, system 
allocator; same PyArrow, only `libarrow_compute` swapped between the two 
commits. `equal alone` is the comparison over the same values, a lower bound 
for the kernel.
   
   ```python
   """Time pc.list_contains against the `equal` pass it is built on. Run once 
per build."""
   
   import json
   import sys
   import time
   
   import numpy as np
   import pyarrow as pa
   import pyarrow.compute as pc
   
   N_VALUES = 50_000_000
   CASES = [(1, 1e-5), (3, 1e-5), (3, 0.3), (10, 0.3), (100, 0.3), (1000, 
1e-5), (1000, 0.3)]
   
   
   def best_ms(func, repeats=7):
       times = []
       for _ in range(repeats):
           start = time.perf_counter()
           func()
           times.append(time.perf_counter() - start)
       return min(times) * 1e3
   
   
   results = {}
   for list_length, match_rate in CASES:
       rng = np.random.default_rng(42)
       values = rng.integers(2, 1 << 40, N_VALUES)
       values[rng.random(N_VALUES) < match_rate] = 1
       offsets = np.arange(0, N_VALUES + 1, list_length, dtype=np.int32)
       lists = pa.ListArray.from_arrays(offsets, pa.array(values))
       flat = lists.values
       item = pa.scalar(1, pa.int64())
       results[f"{list_length},{match_rate}"] = {
           "list_contains": best_ms(lambda: pc.list_contains(lists, item)),
           "equal": best_ms(lambda: pc.equal(flat, item)),
       }
   json.dump(results, sys.stdout)
   ```
   
   </details>


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to