Skip to content

Commit c423152

Browse files
Merge pull request #7 from flaviomartins/update_build_1
Reapply "Update build review"
2 parents f37e29a + c758ca0 commit c423152

46 files changed

Lines changed: 2810 additions & 1351 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/buildwheels.yml

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
name: Build and upload wheels
2+
3+
on:
4+
push:
5+
tags:
6+
- 'v[0-9]+\.[0-9]+\.[0-9]+'
7+
pull_request: # Test builds on PR
8+
workflow_dispatch: # Allows manual triggering
9+
10+
# The Python project lives in the python_bindings/ subdirectory and reaches the
11+
# C++ sources through a `fastpfor` symlink to the repository root. That symlink
12+
# is fine for local builds but does not survive being copied into cibuildwheel's
13+
# build containers (and is not preserved on Windows checkouts). To stay portable
14+
# we build a self-contained sdist first (it bundles the real header/source
15+
# files) and build every wheel from that extracted sdist.
16+
jobs:
17+
build_sdist:
18+
name: Build source distribution
19+
runs-on: ubuntu-latest
20+
steps:
21+
- uses: actions/checkout@v7
22+
23+
- name: Install uv
24+
uses: astral-sh/setup-uv@v10.0.1
25+
26+
- name: Build sdist
27+
run: uv build --sdist
28+
working-directory: python_bindings
29+
30+
- uses: actions/upload-artifact@v7
31+
with:
32+
name: sdist-artifact
33+
path: python_bindings/dist/*.tar.gz
34+
if-no-files-found: error
35+
36+
build_wheels:
37+
name: Build wheels on ${{ matrix.os }}
38+
needs: build_sdist
39+
runs-on: ${{ matrix.os }}
40+
strategy:
41+
fail-fast: false
42+
matrix:
43+
# Native runners for each architecture we publish: x86_64 Linux,
44+
# aarch64 Linux, x86_64 macOS, Apple Silicon macOS, and x86_64 Windows.
45+
# macos-latest currently tracks macos-26 (arm64); macos-26-intel keeps
46+
# the x86_64 macOS build on the same OS/Xcode generation.
47+
# See available runner images/labels: https://github.com/actions/runner-images
48+
os: [ubuntu-24.04, ubuntu-24.04-arm, macos-26-intel, macos-26, windows-latest]
49+
50+
steps:
51+
- uses: actions/download-artifact@v8
52+
with:
53+
name: sdist-artifact
54+
path: dist
55+
56+
- name: Unpack sdist
57+
shell: bash
58+
run: |
59+
mkdir -p sdist_src
60+
tar -xzf dist/*.tar.gz -C sdist_src --strip-components=1
61+
62+
- name: Build wheels
63+
uses: pypa/cibuildwheel@v4.2.1
64+
with:
65+
package-dir: sdist_src
66+
67+
- uses: actions/upload-artifact@v7
68+
with:
69+
name: wheel-artifact-${{ matrix.os }}
70+
path: ./wheelhouse/*.whl
71+
if-no-files-found: error
72+
73+
upload_pypi:
74+
needs: [build_wheels, build_sdist]
75+
runs-on: ubuntu-latest
76+
# Only upload to PyPI when triggered by a tag (not manual workflow_dispatch).
77+
if: startsWith(github.ref, 'refs/tags/')
78+
steps:
79+
- uses: actions/download-artifact@v8
80+
with:
81+
path: dist
82+
merge-multiple: true
83+
84+
- uses: pypa/gh-action-pypi-publish@v1.14.2
85+
with:
86+
user: __token__
87+
password: ${{ secrets.PYPI_API_TOKEN }}

.gitignore

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# Byte-compiled / optimized / DLL files
2+
__pycache__/
3+
*.py[cod]
4+
*$py.class
5+
6+
# C/C++ extensions and objects
7+
*.so
8+
*.o
9+
*.a
10+
11+
# Distribution / packaging
12+
.Python
13+
env/
14+
venv/
15+
build/
16+
develop-eggs/
17+
dist/
18+
eggs/
19+
.eggs/
20+
sdist/
21+
var/
22+
wheels/
23+
wheelhouse/
24+
*.egg-info/
25+
*.egg
26+
27+
# CMake build directories
28+
cmake-build-*/
29+
30+
# Editor / OS cruft
31+
.DS_Store
32+
*.swp

.travis.yml

Lines changed: 0 additions & 63 deletions
This file was deleted.

CMakeLists.txt

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,13 @@
33
# Apache License Version 2.0 http://www.apache.org/licenses/.
44
#
55
# This is a modified version of the CMakeFile
6-
# for the project https://github.com/lemire/FastPFor
7-
# This file can be used to
6+
# for the project https://github.com/lemire/FastPFor
7+
# This file can be used to
88
# 1) Build a library separately. Then, this library
99
# will be re-used by the Python build process
1010
# 2) Build and run unit and performance tests.
1111
#
12-
cmake_minimum_required(VERSION 2.8.7)
12+
cmake_minimum_required(VERSION 3.10)
1313
if (NOT CMAKE_BUILD_TYPE)
1414
message(STATUS "No build type selected, default to Release")
1515
set(CMAKE_BUILD_TYPE Release CACHE STRING "Choose the type of build." FORCE)
@@ -21,7 +21,7 @@ include(AppendCompilerFlags)
2121

2222

2323
project(PyFastPFor CXX C)
24-
set(PROJECT_URL "https://github.com/searchivarius/PyFastPFOR")
24+
set(PROJECT_URL "https://github.com/fast-pack/PyFastPFOR")
2525
set(PROJECT_DESCRIPTION "Python bindings for the FastPFOR C++ library: Fast integer compression")
2626
include(DetectCPUFeatures)
2727
#
@@ -54,8 +54,10 @@ MESSAGE( STATUS "CMAKE_C_COMPILER: " ${CMAKE_C_COMPILER} )
5454
MESSAGE( STATUS "CXX_COMPILER_VERSION: " ${CXX_COMPILER_VERSION} )
5555
if( SUPPORT_SSE42 )
5656
MESSAGE( STATUS "SSE 4.2 support detected" )
57+
elseif( SUPPORT_NEON )
58+
MESSAGE( STATUS "ARM NEON detected: SSE intrinsics are emulated via fastpfor_neon.h" )
5759
else()
58-
MESSAGE( STATUS "SSE 4.2 support not detected" )
60+
MESSAGE( STATUS "Neither SSE 4.2 nor ARM NEON support detected" )
5961
endif()
6062

6163
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
@@ -79,14 +81,21 @@ elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Intel")
7981
set (CMAKE_CXX_FLAGS_DEBUG "-Wall -ggdb -std=c++11 -DHAVE_CXX0X -march=native")
8082
set (CMAKE_C_FLAGS_RELEASE "-Wall -Ofast -DNDEBUG -std=c99 -march=native")
8183
set (CMAKE_C_FLAGS_DEBUG "-Wall -ggdb -std=c99 -march=native")
82-
elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
84+
elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "AppleClang")
8385
if (CXX_COMPILER_VERSION VERSION_LESS 4.2.1)
8486
message(STATUS "Clang version must be at least 4.2.1!" )
8587
endif()
86-
set (CMAKE_CXX_FLAGS_RELEASE "-Wall -Wcast-align -O3 -DNDEBUG -std=c++11 -DHAVE_CXX0X -msse4.1 -march=native")
87-
set (CMAKE_CXX_FLAGS_DEBUG "-Wall -Wcast-align -ggdb -std=c++11 -DHAVE_CXX0X -msse4.1 -march=native")
88-
set (CMAKE_C_FLAGS_RELEASE "-Wall -Wcast-align -O3 -DNDEBUG -std=c99 -msse4.1 -march=native")
89-
set (CMAKE_C_FLAGS_DEBUG "-Wall -Wcast-align -ggdb -std=c99 -msse4.1 -march=native")
88+
# -msse4.1 is x86-only and rejected on ARM; -march=native already enables the
89+
# available SIMD (SSE/AVX on x86, NEON on ARM), so only add it off ARM.
90+
if (SUPPORT_NEON)
91+
set (SIMD_FLAGS "-march=native")
92+
else()
93+
set (SIMD_FLAGS "-msse4.1 -march=native")
94+
endif()
95+
set (CMAKE_CXX_FLAGS_RELEASE "-Wall -Wcast-align -O3 -DNDEBUG -std=c++11 -DHAVE_CXX0X ${SIMD_FLAGS}")
96+
set (CMAKE_CXX_FLAGS_DEBUG "-Wall -Wcast-align -ggdb -std=c++11 -DHAVE_CXX0X ${SIMD_FLAGS}")
97+
set (CMAKE_C_FLAGS_RELEASE "-Wall -Wcast-align -O3 -DNDEBUG -std=c99 ${SIMD_FLAGS}")
98+
set (CMAKE_C_FLAGS_DEBUG "-Wall -Wcast-align -ggdb -std=c99 ${SIMD_FLAGS}")
9099
elseif(WIN32)
91100
# TODO add support for later versions?
92101
if(NOT MSVC12)

README.md

Lines changed: 55 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
[![PyPI version](https://img.shields.io/pypi/v/pyfastpfor.svg)](https://pypi.python.org/pypi/pyfastpfor/)
22
[![Downloads](https://pepy.tech/badge/pyfastpfor)](https://pepy.tech/project/pyfastpfor)
3+
34
# PyFastPFor
5+
46
Python bindings for the fast **light-weight** integer compression library [FastPFor](https://github.com/lemire/FastPFor): A research library with integer compression schemes. FastPFor is broadly applicable to the compression of arrays of 32-bit integers where most integers are small. The library seeks to exploit SIMD instructions (SSE) whenever possible. This library can decode at least 4 billions of compressed integers per second on most desktop or laptop processors. That is, it can decompress data at a rate of 15 GB/s. This is significantly faster than generic codecs like gzip, LZO, Snappy or LZ4.
57

68
# Authors
@@ -9,31 +11,72 @@ Daniel Lemire, Leonid Boytsov, Owen Kaser, Maxime Caron, Louis Dionne, Michel Le
911

1012
# Installation
1113

12-
Bindings can be installed locally:
14+
Install the latest release from PyPI:
15+
16+
```
17+
pip install pyfastpfor
18+
```
19+
20+
### Using uv (recommended)
21+
22+
[uv](https://github.com/astral-sh/uv) is a fast Python package installer and resolver.
23+
24+
To add PyFastPFor as a dependency to your project:
25+
26+
```
27+
uv add pyfastpfor
28+
```
29+
30+
Or to install it directly into your current environment:
31+
32+
```
33+
uv pip install pyfastpfor
34+
```
35+
36+
### Building from source
37+
38+
From the repository root, run:
39+
1340
```
1441
cd python_bindings
15-
pip install -r requirements.txt
16-
sudo setup.py build install
1742
```
18-
or via pip:
43+
44+
With uv:
45+
1946
```
20-
pip install pyfastpfor
47+
uv build
48+
uv pip install dist/*.whl
2149
```
22-
Due to some compilation quirks this currently seem to work with GCC only. I will fix it in some not so distant future. You may also need to install Python dev-files. On Ubuntu, for Python 3 you can do it as follows:
50+
51+
Or with standard tools:
2352

2453
```
25-
sudo apt-get install python3-dev
54+
pip install build
55+
python -m build
56+
pip install dist/*.whl
2657
```
2758

59+
Debug information is disabled by default. To include it in a local build, set
60+
`PYFASTPFOR_DEBUG_INFO=1` when building:
61+
62+
```
63+
PYFASTPFOR_DEBUG_INFO=1 python -m build
64+
```
65+
66+
The bindings build with GCC, Clang, or MSVC, on both x86-64 (SSE/AVX) and ARM/aarch64 (NEON, including Apple Silicon). You may also need to install Python dev-files. On Ubuntu, for Python 3 you can do it as follows:
67+
68+
```
69+
sudo apt-get install python3-dev
70+
```
2871

2972
# Documentation
3073

31-
The library supports all the codecs implemented in the original [FastPFor](https://github.com/lemire/FastPFor) library by July 2023. To get a list of codecs, use the function ``getCodecList``.
74+
The library supports all the codecs implemented in the original [FastPFor](https://github.com/lemire/FastPFor) library (v0.5.0). To get a list of codecs, use the function ``getCodecList``.
3275

33-
Typical light-weight compression does not take context into account and, consequently, works well only for small integers. When integers are large, data differencing is a common trick to make integers small. In particular, we often deal with sorted lists of integers, which can be represented by differences between neighboring numbers.
76+
Typical light-weight compression does not take context into account and, consequently, works well only for small integers. When integers are large, data differencing is a common trick to make integers small. In particular, we often deal with sorted lists of integers, which can be represented by differences between neighboring numbers.
3477

35-
The smallest differences (**fine** deltas) are between adjacent numbers. Respective differencing and difference inverting functions are ``delta1'' and ``prefixSum1''.
78+
The smallest differences (**fine** deltas) are between adjacent numbers. Respective differencing and difference inverting functions are ``delta1'' and``prefixSum1''.
3679

37-
However, we can do reasonably well, we compute differences between numbers that are four positions apart (**coarse** deltas). Such differences can be computed and inverted more efficiently. Respective differencing and difference inverting functions are ``delta4'' and ``prefixSum4''.
80+
However, we can do reasonably well, we compute differences between numbers that are four positions apart (**coarse** deltas). Such differences can be computed and inverted more efficiently. Respective differencing and difference inverting functions are ``delta4'' and``prefixSum4''.
3881

39-
Examples of three common use scenarios (no differencing, coarse and fine deltas) are outlined in [this Python notebook](python_bindings/examples.ipynb).
82+
Examples of three common use scenarios (no differencing, coarse and fine deltas) are outlined in [this Python notebook](python_bindings/examples.ipynb).

cmake_modules/DetectCPUFeatures.cmake

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,17 @@ else()
4747
check_cxx_source_compiles("${AVXPROG}" SUPPORT_AVX)
4848
set(CMAKE_REQUIRED_FLAGS "-march=native -mavx2")
4949
check_cxx_source_compiles("${AVX2PROG}" SUPPORT_AVX2)
50-
endif()
50+
endif()
5151

5252
set(CMAKE_REQUIRED_FLAGS ${OLD_CMAKE_REQUIRED_FLAGS})
53+
54+
# On ARM the SSE intrinsics used throughout FastPFor are provided by the
55+
# fastpfor_neon.h shim (mapped onto NEON), so there is no SSE4.2 support but the
56+
# code still compiles. Flag ARM builds so the SIMD-specific compiler options
57+
# (e.g. -msse4.1) can be skipped.
58+
if (CMAKE_SYSTEM_PROCESSOR MATCHES "arm64" OR CMAKE_SYSTEM_PROCESSOR MATCHES "arm"
59+
OR CMAKE_SYSTEM_PROCESSOR MATCHES "aarch64"
60+
OR CMAKE_GENERATOR_PLATFORM MATCHES "ARM64" OR CMAKE_GENERATOR_PLATFORM MATCHES "ARM")
61+
set(SUPPORT_NEON ON)
62+
endif ()
5363

headers/VarIntG8IU.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
* This code is released under the
33
* Apache License Version 2.0 http://www.apache.org/licenses/.
44
*/
5-
#if !defined(__SSSE3__) && !(defined(_MSC_VER) && defined(__AVX__))
5+
#if (!defined(__SSSE3__) && !(defined(_MSC_VER) && defined(__AVX__))) && !(defined(__ARM_NEON) || defined(__aarch64__))
66
#ifndef _MSC_VER
77
#pragma message \
88
"Disabling varintg8iu due to lack of SSSE3 support, try adding -mssse3 or the equivalent on your compiler"
@@ -12,7 +12,12 @@
1212
#else
1313
#ifndef VARINTG8IU_H__
1414
#define VARINTG8IU_H__
15+
#if defined(__GNUC__) && (defined(__x86_64__) || defined(__i386__))
1516
#include <emmintrin.h>
17+
#elif defined(__aarch64__)
18+
/* GCC-compatible compiler, targeting ARM with native NEON */
19+
#include "fastpfor_neon.h"
20+
#endif
1621
#include "codecs.h"
1722
#ifdef __GNUC__
1823
#define PREDICT_FALSE(x) (__builtin_expect(x, 0))

headers/blockpacking.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -286,6 +286,7 @@ class ByteAlignedPacking : public IntegerCODEC {
286286

287287
const uint32_t *decodeArray(const uint32_t *in, const size_t length,
288288
uint32_t *out, size_t &nvalue) {
289+
(void)length;
289290
const uint32_t actuallength = *in++;
290291
const uint8_t *inbyte = reinterpret_cast<const uint8_t *>(in);
291292
const uint32_t *const initout(out);

0 commit comments

Comments
 (0)