You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@iceberg.apache.org by "kevinjqliu (via GitHub)" <gi...@apache.org> on 2024/10/28 22:21:46 UTC

[I] explore removing `numpy` [iceberg-python]

kevinjqliu opened a new issue, #1259:
URL: https://github.com/apache/iceberg-python/issues/1259

   ### Feature Request / Improvement
   
   #1256 mentioned removing `numpy` as a dependency. `numpy` is currently only used in 1 function
   https://github.com/apache/iceberg-python/blob/583a7e97db28afa4259cdf504611845222338893/pyiceberg/io/pyarrow.py#L810-L815
   and 2 tests
   https://github.com/apache/iceberg-python/blob/583a7e97db28afa4259cdf504611845222338893/tests/integration/test_writes/test_writes.py#L1348-L1383
   https://github.com/apache/iceberg-python/blob/583a7e97db28afa4259cdf504611845222338893/tests/integration/test_writes/test_writes.py#L1404-L1412
   
   It seems like we can replace the `_combine_positional_deletes` use of `numpy` with pure python operators or pyarrow operators
   
   


-- 
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: issues-unsubscribe@iceberg.apache.org.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


Re: [I] explore removing `numpy` as a dependency [iceberg-python]

Posted by "kevinjqliu (via GitHub)" <gi...@apache.org>.
kevinjqliu commented on issue #1259:
URL: https://github.com/apache/iceberg-python/issues/1259#issuecomment-2442788004

   This ChatGPT-generated function seems to be logically equivalent. And pass integration tests. 
   But we should double check this 
   
   ```
   def _combine_positional_deletes(positional_deletes: List[pa.ChunkedArray], start_index: int, end_index: int) -> pa.Array:
       if len(positional_deletes) == 1:
           all_chunks = positional_deletes[0]
       else:
           all_chunks = pa.chunked_array(itertools.chain(*[arr.chunks for arr in positional_deletes]))
       
       # Create the full range array with pyarrow
       full_range = pa.array(range(start_index, end_index))
       
       # Filter out values in all_chunks from full_range
       result = pc.filter(full_range, pc.invert(pc.is_in(full_range, value_set=all_chunks)))
       
       # Subtract the start_index from each element in the result
       adjusted_result = pc.subtract(result, pa.scalar(start_index))
       
       return adjusted_result
   ```


-- 
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: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


Re: [I] Remove `numpy` as a dependency [iceberg-python]

Posted by "Fokko (via GitHub)" <gi...@apache.org>.
Fokko commented on issue #1259:
URL: https://github.com/apache/iceberg-python/issues/1259#issuecomment-2444005081

   @kevinjqliu That looks about right to me :) Could you do some benchmarking to see if we don't get too much of a performance regression?


-- 
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: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


Re: [I] Remove `numpy` as a dependency [iceberg-python]

Posted by "corleyma (via GitHub)" <gi...@apache.org>.
corleyma commented on issue #1259:
URL: https://github.com/apache/iceberg-python/issues/1259#issuecomment-2448429340

   Arrow's release cycles are... not quick, but I have no doubt that logic will land there at some point.


-- 
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: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


Re: [I] Remove `numpy` as a dependency [iceberg-python]

Posted by "Fokko (via GitHub)" <gi...@apache.org>.
Fokko commented on issue #1259:
URL: https://github.com/apache/iceberg-python/issues/1259#issuecomment-2446285669

   I took the liberty of checking this, so we can fix this for 0.8.0:
   
   ![image](https://github.com/user-attachments/assets/1711b206-2ce1-429e-b852-bc6fc2f6c556)
   
   It looks like we're spending a lot of time on generating the sequence. I think it would be good to add this to Arrow itself: https://github.com/apache/arrow/issues/44583


-- 
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: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


Re: [I] Remove `numpy` as a dependency [iceberg-python]

Posted by "Fokko (via GitHub)" <gi...@apache.org>.
Fokko closed issue #1259: Remove `numpy` as a dependency
URL: https://github.com/apache/iceberg-python/issues/1259


-- 
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: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


Re: [I] Remove `numpy` as a dependency [iceberg-python]

Posted by "corleyma (via GitHub)" <gi...@apache.org>.
corleyma commented on issue #1259:
URL: https://github.com/apache/iceberg-python/issues/1259#issuecomment-2448393527

   > It looks like we're spending a lot of time on generating the sequence. I think it would be good to add this to Arrow itself: https://github.com/apache/arrow/issues/44583 I think we can move this forward since it doesn't happy very often that a file is affected by multiple positional deletes. Once it has been added to Arrow, we can also add it to PyIceberg
   
   If we wanted, I suspect we could use the pyarrow cython/C++ API to allocate and create the range array much faster.
   
   Something like:
   ```cython
   # range_impl.pyx
   # distutils: language=c++
   
   from pyarrow.lib cimport *
   import pyarrow as pa
   import pyarrow.compute as pc
   from libcpp.memory cimport shared_ptr, make_shared
   from libcpp.vector cimport vector
   from libc.stdint cimport int64_t, uint8_t
   
   cdef extern from "arrow/array.h" namespace "arrow":
       cdef cppclass CInt64Array "arrow::Int64Array":
           CInt64Array(const shared_ptr[CDataType]& type,
                      int64_t length,
                      const shared_ptr[CBuffer]& data)
   
   def create_arrow_range(int64_t start, int64_t end):
       if start >= end:
           raise ValueError("start must be less than end")
           
       cdef:
           vector[int64_t] values
           int64_t i
           shared_ptr[CArray] out
           shared_ptr[CBuffer] buffer
           shared_ptr[CDataType] dtype
       
       # Pre-allocate the vector size
       values.reserve(end - start)
       
       # Fill vector with range values
       for i in range(start, end):
           values.push_back(i)
       
       # Create buffer from vector data
       buffer = make_shared[CBuffer](
           <uint8_t*>values.data(),
           values.size() * sizeof(int64_t)
       )
       
       # Get int64 datatype
       dtype = pyarrow_unwrap_data_type(pa.int64())
       
       # Create Int64Array
       out = make_shared[CInt64Array](dtype, end - start, buffer)
       
       # Wrap and return as Python object
       return pyarrow_wrap_array(out)
    
   ```
   
   ```python
   # setup.py
   import os
   
   import pyarrow as pa
   from Cython.Build import cythonize
   from setuptools import Extension, setup
   
   # Ensure you have the Arrow C++ shared libraries available
   try:
       pa.create_library_symlinks()
   except:
       pass
   
   ext_modules = cythonize(
       "range_impl.pyx",
       compiler_directives={
           "language_level": "3",
           "embedsignature": True,
       },
   )
   
   for ext in ext_modules:
       # We only need numpy headers at build time
       ext.include_dirs.append(pa.get_include())
       ext.libraries.extend(pa.get_libraries())
       ext.library_dirs.extend(pa.get_library_dirs())
   
       # Enable C++17
       if os.name == "posix":
           ext.extra_compile_args.append("-std=c++17")
   
   setup(
       name="arrow_range",
       ext_modules=ext_modules,
       setup_requires=["pyarrow"],  # Only needed during build
       install_requires=["pyarrow"],  # Runtime dependency
   )
   ```
   
   and using this to benchmark:
   ```python
   # benchmark.py
   import time
   
   import pyarrow as pa
   
   from range_impl import create_arrow_range
   
   
   def test_python_range(start, end):
       return pa.array(range(start, end))
   
   
   def test_cython_range(start, end):
       return create_arrow_range(start, end)
   
   
   def benchmark(start, end, n_runs=5):
       times_python = []
       times_cython = []
   
       print(f"Testing range from {start} to {end} ({end-start} elements)")
   
       # Warm up
       _ = test_python_range(0, 1000)
       _ = test_cython_range(0, 1000)
   
       for i in range(n_runs):
           # Test Python range
           t0 = time.perf_counter()
           arr_py = test_python_range(start, end)
           t1 = time.perf_counter()
           times_python.append(t1 - t0)
   
           # Test Cython range
           t0 = time.perf_counter()
           arr_cy = test_cython_range(start, end)
           t1 = time.perf_counter()
           times_cython.append(t1 - t0)
   
           # Verify results match
           assert arr_py.equals(arr_cy), "Arrays don't match!"
   
       avg_python = sum(times_python) / len(times_python)
       avg_cython = sum(times_cython) / len(times_cython)
   
       print(f"Python average: {avg_python:.4f}s")
       print(f"Cython average: {avg_cython:.4f}s")
       print(f"Speedup: {avg_python/avg_cython:.2f}x")
   
   
   if __name__ == "__main__":
       benchmark(0, 10_000_000)  
   ```
   
   Gives me this on my m1:
   ```sh
   python setup.py build_ext --inplace
   python benchmark.py
   running build_ext
   Testing range from 0 to 10000000 (10000000 elements)
   Python average: 0.9227s
   Cython average: 0.0125s
   Speedup: 73.64x
   ```


-- 
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: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


Re: [I] Remove `numpy` as a dependency [iceberg-python]

Posted by "geruh (via GitHub)" <gi...@apache.org>.
geruh commented on issue #1259:
URL: https://github.com/apache/iceberg-python/issues/1259#issuecomment-3060166331

   They added support for the arange function in pyarrow in https://github.com/apache/arrow/pull/46778/files. I pulled the latest Arrow branch, built it locally, and integrated it into PyIceberg. The updated implementation would looks like this:
   
   ```python
   def _combine_positional_deletes(positional_deletes: List[pa.ChunkedArray], start_index: int, end_index: int) -> pa.Array:
       if len(positional_deletes) == 1:
           all_chunks = positional_deletes[0]
       else:
           all_chunks = pa.chunked_array(itertools.chain(*[arr.chunks for arr in positional_deletes]))
   
       full_range = pa.arange(start_index, end_index)
   
       result = pc.filter(full_range, pc.invert(pc.is_in(full_range, value_set=all_chunks)))
   
       return pc.subtract(result, pa.scalar(start_index))
   ```
   
   Using the benchmark from @corleyma, I get roughly:
   
   ```
   Testing range from 0 to 10000000 (10000000 elements)
   Python average: 0.6944s
   Cython average: 0.0096s
   Speedup: 71.96x
   ```
   
   Maybe in the next arrow release we can add this if an upgrade isn't to burdensome.


-- 
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: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


Re: [I] Remove `numpy` as a dependency [iceberg-python]

Posted by "Fokko (via GitHub)" <gi...@apache.org>.
Fokko commented on issue #1259:
URL: https://github.com/apache/iceberg-python/issues/1259#issuecomment-2449171063

   Hey @corleyma that looks awesome, and that's some amazing speedup 🤤 I think the best place to put this would be Arrow itself.


-- 
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: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org


Re: [I] Remove `numpy` as a dependency [iceberg-python]

Posted by "kevinjqliu (via GitHub)" <gi...@apache.org>.
kevinjqliu commented on issue #1259:
URL: https://github.com/apache/iceberg-python/issues/1259#issuecomment-2448411602

   supercool! As a project, I don't want to maintain an implementation of the `range` function 😄 Is there a way to contribute `create_arrow_range` to Arrow? 


-- 
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: issues-unsubscribe@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@iceberg.apache.org
For additional commands, e-mail: issues-help@iceberg.apache.org