Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make qsimcirq Apple Silicon (M1, M2, ARM64) compatible and improve build scripts #643

Merged
merged 21 commits into from
Nov 29, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions .github/workflows/release_wheels.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,14 @@ jobs:
fail-fast: false
matrix:
include:
- os: macos-12
- os: macos-12 # x86_64
name: mac
cibw:
build: "cp37* cp38* cp39* cp310* cp311*"
- os: macos-13-large # Apple Silicon
name: mac_arm64
cibw:
build: "cp37* cp38* cp39* cp310* cp311*"
- os: ubuntu-20.04
name: manylinux2014
cibw:
Expand All @@ -32,7 +36,7 @@ jobs:
CIBW_SKIP: "*musllinux*"
CIBW_ARCHS: "${{ matrix.cibw.arch || 'auto' }}"
CIBW_MANYLINUX_X86_64_IMAGE: "${{ matrix.cibw.manylinux_image }}"
CIBW_BEFORE_BUILD_MACOS: "brew install libomp llvm"
CIBW_BEFORE_BUILD_MACOS: "brew install libomp llvm && brew link --overwrite [email protected] && brew link --force libomp"
CIBW_REPAIR_WHEEL_COMMAND_MACOS: "delocate-listdeps {wheel} && delocate-wheel --verbose --require-archs {delocate_archs} -w {dest_dir} {wheel}"
# to install latest delocate package
CIBW_DEPENDENCY_VERSIONS: "latest"
Expand Down
8 changes: 6 additions & 2 deletions .github/workflows/testing_wheels.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,14 @@ jobs:
fail-fast: false
matrix:
include:
- os: macos-12
- os: macos-12 # x86_64
name: mac
cibw:
build: "cp37* cp38* cp39* cp310* cp311*"
- os: macos-13-large # Apple Silicon
name: mac_arm64
cibw:
build: "cp37* cp38* cp39* cp310* cp311*"
- os: ubuntu-20.04
name: manylinux2014
cibw:
Expand All @@ -37,7 +41,7 @@ jobs:
CIBW_SKIP: "*musllinux*"
CIBW_ARCHS: "${{ matrix.cibw.arch || 'auto' }}"
CIBW_MANYLINUX_X86_64_IMAGE: "${{ matrix.cibw.manylinux_image }}"
CIBW_BEFORE_BUILD_MACOS: "brew install libomp llvm"
CIBW_BEFORE_BUILD_MACOS: "brew install libomp llvm && brew link --overwrite [email protected] && brew link --force libomp"
CIBW_REPAIR_WHEEL_COMMAND_MACOS: "delocate-listdeps {wheel} && delocate-wheel --verbose --require-archs {delocate_archs} -w {dest_dir} {wheel}"
# to install latest delocate package
CIBW_DEPENDENCY_VERSIONS: "latest"
Expand Down
57 changes: 42 additions & 15 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,24 +1,51 @@
set(CMAKE_CXX_STANDARD 11)
cmake_minimum_required(VERSION 3.11)

execute_process(COMMAND which nvcc OUTPUT_VARIABLE has_nvcc)
if(has_nvcc STREQUAL "")
execute_process(COMMAND which hipcc OUTPUT_VARIABLE has_hipcc)
if(has_hipcc STREQUAL "")
project(qsim)
else()
project(qsim LANGUAGES CXX HIP)
ADD_SUBDIRECTORY(pybind_interface/hip)
# Set APPLE_ARM to TRUE if running on Apple Silicon
if(APPLE)
execute_process(COMMAND uname -m OUTPUT_VARIABLE OSX_ARCH OUTPUT_STRIP_TRAILING_WHITESPACE)
if (OSX_ARCH STREQUAL "arm64")
set(APPLE_ARM TRUE)
else() # x86_64
set(APPLE_ARM FALSE)
endif()
else()
project(qsim LANGUAGES CXX CUDA)
ADD_SUBDIRECTORY(pybind_interface/cuda)
if(DEFINED ENV{CUQUANTUM_ROOT})
ADD_SUBDIRECTORY(pybind_interface/custatevec)
set(APPLE_ARM FALSE)
endif(APPLE)

# Set the project name and language
if(APPLE)
project(qsim LANGUAGES CXX)
else()
execute_process(COMMAND which nvcc OUTPUT_VARIABLE has_nvcc OUTPUT_STRIP_TRAILING_WHITESPACE)
if(has_nvcc)
project(qsim LANGUAGES CXX CUDA)
else()
execute_process(COMMAND which hipcc OUTPUT_VARIABLE has_hipcc OUTPUT_STRIP_TRAILING_WHITESPACE)
if(has_hipcc)
project(qsim LANGUAGES CXX HIP)
else()
project(qsim LANGUAGES CXX)
endif()
endif()
endif()

ADD_SUBDIRECTORY(pybind_interface/sse)
ADD_SUBDIRECTORY(pybind_interface/avx512)
ADD_SUBDIRECTORY(pybind_interface/avx2)
find_package(OpenMP REQUIRED)

# Add subdirectories based on the architecture or available compilers
ADD_SUBDIRECTORY(pybind_interface/basic)
ADD_SUBDIRECTORY(pybind_interface/decide)
if(NOT APPLE_ARM)
if(has_nvcc)
ADD_SUBDIRECTORY(pybind_interface/cuda)
if(DEFINED ENV{CUQUANTUM_ROOT})
ADD_SUBDIRECTORY(pybind_interface/custatevec)
endif()
elseif(has_hipcc)
ADD_SUBDIRECTORY(pybind_interface/hip)
endif()

ADD_SUBDIRECTORY(pybind_interface/sse)
ADD_SUBDIRECTORY(pybind_interface/avx512)
ADD_SUBDIRECTORY(pybind_interface/avx2)
endif()
15 changes: 15 additions & 0 deletions pybind_interface/GetPybind11.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,21 @@ FetchContent_Declare(
)
FetchContent_GetProperties(pybind11)
find_package(pybind11 "${MIN_PYBIND_VERSION}" CONFIG)

if (pybind11_FOUND)
message(STATUS "Found pybind11 v${pybind11_VERSION}: ${pybind11_INCLUDE_DIRS}")
# The pybind11_add_module doesn't correctly set the CXX_INCLUDES properly if a system pybind11 is found.
# Using `include_directories(${pybind11_INCLUDE_DIRS})` doesn't result in anything in
# CXX_INCLUDES. e.g., `pybind_interface/basic/CMakeFiles/qsim_basic.dir/flags.make` would only
# have `CXX_INCLUDES = -isystem $PREFIX/include/python3.11` and would miss `$PREFIX/include`.
# This problem would result in `fatal error: pybind11/complex.h: No such file or directory`
# This is a hack to get around that by passing `-I/path/to/include` to CXX_FLAGS
# Iterate over each include directory and add it as a compile option
foreach(INCLUDE_DIR ${pybind11_INCLUDE_DIRS})
add_compile_options("-I${INCLUDE_DIR}")
endforeach()
endif()

if((NOT pybind11_FOUND) AND (NOT pybind11_POPULATED)) # check first on system path, then attempt git fetch
FetchContent_Populate(pybind11)
add_subdirectory(${pybind11_SOURCE_DIR} ${pybind11_BINARY_DIR})
Expand Down
4 changes: 3 additions & 1 deletion pybind_interface/avx2/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ project(qsim)
IF (WIN32)
set(CMAKE_CXX_FLAGS "/arch:AVX2 /O2 /openmp")
ELSE()
set(CMAKE_CXX_FLAGS "-mavx2 -mfma -O3 -fopenmp")
set(CMAKE_CXX_FLAGS "-mavx2 -mfma -O3")
ENDIF()

if(APPLE)
Expand All @@ -14,3 +14,5 @@ if(APPLE)
endif()
INCLUDE(../GetPybind11.cmake)
pybind11_add_module(qsim_avx2 pybind_main_avx2.cpp)

target_link_libraries(qsim_avx2 PUBLIC OpenMP::OpenMP_CXX)
4 changes: 3 additions & 1 deletion pybind_interface/avx512/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ project(qsim)
IF (WIN32)
set(CMAKE_CXX_FLAGS "/arch:AVX512 /O2 /openmp")
ELSE()
set(CMAKE_CXX_FLAGS "-mavx512f -mbmi2 -O3 -fopenmp")
set(CMAKE_CXX_FLAGS "-mavx512f -mbmi2 -O3")
ENDIF()

if(APPLE)
Expand All @@ -16,3 +16,5 @@ endif()

INCLUDE(../GetPybind11.cmake)
pybind11_add_module(qsim_avx512 pybind_main_avx512.cpp)

target_link_libraries(qsim_avx512 PUBLIC OpenMP::OpenMP_CXX)
10 changes: 6 additions & 4 deletions pybind_interface/basic/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
cmake_minimum_required(VERSION 3.11)
project(qsim)

IF (WIN32)
if(WIN32)
set(CMAKE_CXX_FLAGS "/O2 /openmp")
ELSE()
set(CMAKE_CXX_FLAGS "-O3 -fopenmp")
ENDIF()
else()
set(CMAKE_CXX_FLAGS "-O3")
endif()


if(APPLE)
Expand All @@ -16,3 +16,5 @@ endif()

INCLUDE(../GetPybind11.cmake)
pybind11_add_module(qsim_basic pybind_main_basic.cpp)

target_link_libraries(qsim_basic PUBLIC OpenMP::OpenMP_CXX)
10 changes: 6 additions & 4 deletions pybind_interface/cuda/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
cmake_minimum_required(VERSION 3.11)
project(qsim LANGUAGES CXX CUDA)

IF (WIN32)
if(WIN32)
set(CMAKE_CXX_FLAGS "/O2 /openmp")
ELSE()
set(CMAKE_CXX_FLAGS "-O3 -fopenmp")
ENDIF()
else()
set(CMAKE_CXX_FLAGS "-O3")
endif()


if(APPLE)
Expand All @@ -26,3 +26,5 @@ set_target_properties(qsim_cuda PROPERTIES
SUFFIX "${PYTHON_MODULE_EXTENSION}"
)
set_source_files_properties(pybind_main_cuda.cpp PROPERTIES LANGUAGE CUDA)

target_link_libraries(qsim_cuda PUBLIC OpenMP::OpenMP_CXX)
10 changes: 6 additions & 4 deletions pybind_interface/custatevec/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,11 @@
cmake_minimum_required(VERSION 3.11)
project(qsim LANGUAGES CXX CUDA)

IF (WIN32)
if(WIN32)
set(CMAKE_CXX_FLAGS "/O2 /openmp")
ELSE()
set(CMAKE_CXX_FLAGS "-O3 -fopenmp")
ENDIF()
else()
set(CMAKE_CXX_FLAGS "-O3")
endif()

if(APPLE)
set(CMAKE_CXX_STANDARD 14)
Expand All @@ -44,3 +44,5 @@ set_target_properties(qsim_custatevec PROPERTIES
SUFFIX "${PYTHON_MODULE_EXTENSION}"
)
set_source_files_properties(pybind_main_custatevec.cpp PROPERTIES LANGUAGE CUDA)

target_link_libraries(qsim_custatevec PUBLIC OpenMP::OpenMP_CXX)
80 changes: 31 additions & 49 deletions pybind_interface/decide/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,66 +1,48 @@
cmake_minimum_required(VERSION 3.11)

execute_process(COMMAND which nvcc OUTPUT_VARIABLE has_nvcc)
if(has_nvcc STREQUAL "")
execute_process(COMMAND which hipcc OUTPUT_VARIABLE has_hipcc)
if(has_hipcc STREQUAL "")
project(qsim)
else()
project(qsim LANGUAGES CXX HIP)
endif()
if(WIN32)
set(CMAKE_CXX_FLAGS "/O2 /openmp")
else()
project(qsim LANGUAGES CXX CUDA)
set(CMAKE_CXX_FLAGS "-O3")
endif()

IF (WIN32)
set(CMAKE_CXX_FLAGS "/O2 /openmp")
ELSE()
set(CMAKE_CXX_FLAGS "-O3 -fopenmp")
ENDIF()

if(APPLE)
if(APPLE AND NOT APPLE_ARM)
set(CMAKE_CXX_STANDARD 14)
include_directories("/usr/local/include" "/usr/local/opt/llvm/include")
link_directories("/usr/local/lib" "/usr/local/opt/llvm/lib")
endif()

INCLUDE(../GetPybind11.cmake)

if(has_nvcc STREQUAL "")
if(has_hipcc STREQUAL "")
pybind11_add_module(qsim_decide decide.cpp)
else()
include(../GetPybind11.cmake)

# Configure based on the detected platform
if(has_nvcc)
find_package(CUDA REQUIRED)
cuda_add_library(qsim_decide MODULE decide.cpp)
if(DEFINED ENV{CUQUANTUM_ROOT})
target_compile_options(qsim_decide PRIVATE
$<$<COMPILE_LANGUAGE:CUDA>:-D__CUSTATEVEC__>
)
endif()
find_package(Python3 3.7 REQUIRED COMPONENTS Interpreter Development)
include_directories(${PYTHON_INCLUDE_DIRS} ${pybind11_SOURCE_DIR}/include)
set_target_properties(qsim_decide PROPERTIES
PREFIX "${PYTHON_MODULE_PREFIX}"
SUFFIX "${PYTHON_MODULE_EXTENSION}"
)
set_source_files_properties(decide.cpp PROPERTIES LANGUAGE CUDA)
elseif(has_hipcc)
list(APPEND CMAKE_MODULE_PATH "/opt/rocm/lib/cmake/hip")
find_package(HIP REQUIRED)
find_package(PythonLibs 3.7 REQUIRED)

include_directories(${PYTHON_INCLUDE_DIRS} ${pybind11_SOURCE_DIR}/include)

hip_add_library(qsim_decide MODULE decide.cpp)

set_source_files_properties(decide.cpp PROPERTIES LANGUAGE HIP)
find_package(Python3 3.7 REQUIRED COMPONENTS Interpreter Development)
include_directories(${PYTHON_INCLUDE_DIRS} ${pybind11_SOURCE_DIR}/include)
set_target_properties(qsim_decide PROPERTIES
PREFIX "${PYTHON_MODULE_PREFIX}"
SUFFIX "${PYTHON_MODULE_EXTENSION}"
PREFIX "${PYTHON_MODULE_PREFIX}"
SUFFIX "${PYTHON_MODULE_EXTENSION}"
)
set_source_files_properties(decide.cpp PROPERTIES LANGUAGE HIP)
endif()
else()
find_package(PythonLibs 3.7 REQUIRED)
find_package(CUDA REQUIRED)

include_directories(${PYTHON_INCLUDE_DIRS} ${pybind11_SOURCE_DIR}/include)

cuda_add_library(qsim_decide MODULE decide.cpp)

if(DEFINED ENV{CUQUANTUM_ROOT})
target_compile_options(qsim_decide PRIVATE
$<$<COMPILE_LANGUAGE:CUDA>:-D__CUSTATEVEC__>
)
endif()

set_target_properties(qsim_decide PROPERTIES
PREFIX "${PYTHON_MODULE_PREFIX}"
SUFFIX "${PYTHON_MODULE_EXTENSION}"
)
set_source_files_properties(decide.cpp PROPERTIES LANGUAGE CUDA)
pybind11_add_module(qsim_decide decide.cpp)
endif()

target_link_libraries(qsim_decide PUBLIC OpenMP::OpenMP_CXX)
13 changes: 7 additions & 6 deletions pybind_interface/decide/decide.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ namespace py = pybind11;
#include <intrin.h>
#define cpuid(info, x) __cpuidex(info, x, 0)

#else
// GCC Intrinsics
#elif defined(__x86_64__) || defined(__i386__)
// GCC Intrinsics for x86/x86_64
#include <cpuid.h>
void cpuid(int info[4], int infoType){
__cpuid_count(infoType, 0, info[0], info[1], info[2], info[3]);
Expand All @@ -34,10 +34,11 @@ enum Instructions { AVX512F = 0, AVX2 = 1, SSE4_1 = 2, BASIC = 3};

int detect_instructions() {
Instructions instr = BASIC;
int info[4];

#if !defined(__aarch64__) || !defined(__APPLE__)
// Existing x86/x86_64 specific instruction set detection logic
int info[4];
cpuid(info, 0);

int nIds = info[0];
if (nIds >= 1) {
cpuid(info, 1);
Expand All @@ -47,14 +48,14 @@ int detect_instructions() {
}
if (nIds >= 7) {
cpuid(info, 7);
if ((info[1] & (1 << 5))!= 0) {
if ((info[1] & (1 << 5)) != 0) {
instr = AVX2;
}
if ((info[1] & (1 << 16)) != 0) {
instr = AVX512F;
}

}
#endif

return static_cast<int>(instr);
}
Expand Down
10 changes: 6 additions & 4 deletions pybind_interface/hip/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
cmake_minimum_required(VERSION 3.18)
project(qsim LANGUAGES CXX HIP)

IF (WIN32)
if(WIN32)
set(CMAKE_CXX_FLAGS "/O2 /openmp")
ELSE()
set(CMAKE_CXX_FLAGS "-O3 -fopenmp")
ENDIF()
else()
set(CMAKE_CXX_FLAGS "-O3")
endif()

INCLUDE(../GetPybind11.cmake)
find_package(PythonLibs 3.7 REQUIRED)
Expand All @@ -22,3 +22,5 @@ set_target_properties(qsim_hip PROPERTIES
SUFFIX "${PYTHON_MODULE_EXTENSION}"
)
set_source_files_properties(pybind_main_hip.cpp PROPERTIES LANGUAGE HIP)

target_link_libraries(qsim_hip PUBLIC OpenMP::OpenMP_CXX)
Loading