diff --git a/CMakeLists.txt b/CMakeLists.txt index 62850b5b75..606491c27d 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -233,9 +233,11 @@ else() # Standalone build # We build SIMD filed separately, because they will be reached only if the # machine running the code has SIMD support + set(SIMD_SOURCE_FILE "${PROJECT_SOURCE_DIR}/src/simulators/statevector/qubitvector_avx2.cpp") if(APPLE OR UNIX) - set(SIMD_SOURCE_FILE "${PROJECT_SOURCE_DIR}/src/simulators/statevector/qubitvector_avx2.cpp") set_source_files_properties(${SIMD_SOURCE_FILE} PROPERTIES COMPILE_FLAGS "-mfma -mavx2") + elseif(MSVC) + set_source_files_properties(${SIMD_SOURCE_FILE} PROPERTIES COMPILE_FLAGS "/arch:AVX2") endif() set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) diff --git a/qiskit/providers/aer/backends/wrappers/CMakeLists.txt b/qiskit/providers/aer/backends/wrappers/CMakeLists.txt index 386749b29d..50cef05d6f 100644 --- a/qiskit/providers/aer/backends/wrappers/CMakeLists.txt +++ b/qiskit/providers/aer/backends/wrappers/CMakeLists.txt @@ -7,7 +7,7 @@ find_package(Pybind11 REQUIRED) # shared library. string(REPLACE " -static " "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") -# Controllers + if(CUDA_FOUND) set_source_files_properties(bindings.cc PROPERTIES CUDA_SOURCE_PROPERTY_FORMAT OBJ) @@ -15,12 +15,16 @@ endif() # We build SIMD filed separately, because they will be reached only if the # machine running the code has SIMD support +set(SIMD_SOURCE_FILE "../../../../../src/simulators/statevector/qubitvector_avx2.cpp") + if(APPLE OR UNIX) - set(SIMD_SOURCE_FILE "../../../../../src/simulators/statevector/qubitvector_avx2.cpp") set_source_files_properties(${SIMD_SOURCE_FILE} PROPERTIES COMPILE_FLAGS "-mfma -mavx2") +elseif(MSVC) + set_source_files_properties(${SIMD_SOURCE_FILE} PROPERTIES COMPILE_FLAGS "/arch:AVX2") endif() -basic_pybind11_add_module(controller_wrappers bindings.cc ${SIMD_SOURCE_FILE}) + +basic_pybind11_add_module(controller_wrappers ${SIMD_SOURCE_FILE} bindings.cc) target_include_directories(controller_wrappers PRIVATE ${AER_SIMULATOR_CPP_SRC_DIR} PRIVATE ${AER_SIMULATOR_CPP_EXTERNAL_LIBS}) target_link_libraries(controller_wrappers ${AER_LIBRARIES}) diff --git a/src/controllers/qasm_controller.hpp b/src/controllers/qasm_controller.hpp index 90a47fdaf3..1d8b893138 100755 --- a/src/controllers/qasm_controller.hpp +++ b/src/controllers/qasm_controller.hpp @@ -21,11 +21,14 @@ #include "simulators/matrix_product_state/matrix_product_state.hpp" #include "simulators/stabilizer/stabilizer_state.hpp" #include "simulators/statevector/statevector_state.hpp" +#include "simulators/statevector/qubitvector.hpp" +#include "simulators/statevector/qubitvector_avx2.hpp" #include "simulators/superoperator/superoperator_state.hpp" #include "transpile/delay_measure.hpp" #include "transpile/fusion.hpp" #include "framework/avx2_detect.hpp" + namespace AER { namespace Simulator { diff --git a/src/controllers/statevector_controller.hpp b/src/controllers/statevector_controller.hpp index 82b44d4e4d..5fb934417e 100755 --- a/src/controllers/statevector_controller.hpp +++ b/src/controllers/statevector_controller.hpp @@ -17,6 +17,7 @@ #include "controller.hpp" #include "simulators/statevector/statevector_state.hpp" +#include "simulators/statevector/qubitvector_avx2.hpp" namespace AER { namespace Simulator { diff --git a/src/framework/avx2_detect.hpp b/src/framework/avx2_detect.hpp index 0b33532015..25868b984e 100644 --- a/src/framework/avx2_detect.hpp +++ b/src/framework/avx2_detect.hpp @@ -15,51 +15,74 @@ #ifndef _aer_controller_avx2_detect_hpp_ #define _aer_controller_avx2_detect_hpp_ -#ifdef _WIN64 +#ifdef _MSC_VER #include #elif defined(__GNUC__) #include #endif +#include +#include +#include -namespace AER { +namespace { +inline void ccpuid(int cpu_info[4], int function_id){ +#ifdef _MSC_VER + __cpuid(cpu_info, function_id); +#elif defined(__GNUC__) + __cpuid(function_id, + cpu_info[0], + cpu_info[1], + cpu_info[2], + cpu_info[3]); +#else // We don't support this platform intrinsics + cpu_info[0] = cpu_info[1] = cpu_info[2] = cpu_info[3] = 0; +#endif +} -#ifdef __GNUC__ -static void get_cpuid(void* p) { - int* a = (int*) p; - __cpuid(1, a[0], a[1], a[2], a[3]); +inline void cpuidex(int cpu_info[4], int function_id, int subfunction_id){ +#ifdef _MSC_VER + __cpuidex(cpu_info, function_id, subfunction_id); +#elif defined(__GNUC__) + __cpuid_count(function_id, subfunction_id, cpu_info[0], cpu_info[1], cpu_info[2], cpu_info[3]); +#else // We don't support this platform intrinsics + cpu_info[0] = cpu_info[1] = cpu_info[2] = cpu_info[3] = 0; +#endif } -static void get_cpuid_count(void* p) { - int* a = (int*) p; - __cpuid_count(0x00000007, 0, a[0], a[1], a[2], a[3]); } -#endif -inline bool is_avx2_supported() { - static bool cached = false; - static bool is_supported = false; - if(cached) - return is_supported; +namespace AER { -#if defined(__GNUC__) - int info[4] = {0}; - get_cpuid(info); - bool fma = (info[2] >> 12 & 1); - bool avx = (info[2] >> 28 & 1); - if (!fma || !avx){ - cached = true; +inline bool is_avx2_supported(){ + static bool cached = false; + static bool is_supported = false; + if(cached) + return is_supported; + + std::array cpui; + ccpuid(cpui.data(), 0); + auto num_ids = cpui[0]; + if(num_ids < 7){ + cached = true; is_supported = false; return false; + } + + std::vector> data; + for (int i = 0; i <= num_ids; ++i){ + cpuidex(cpui.data(), i, 0); + data.push_back(cpui); } - get_cpuid_count(info); - bool avx2 = (info[1] >> 5 & 1); - cached = true; - is_supported = avx2; - return avx2; -#else - return false; -#endif -} + std::bitset<32> f_1_ECX = data[1][2]; + std::bitset<32> f_7_EBX = data[7][1]; + + bool is_fma_supported = (f_1_ECX[12] & 1); + bool is_avx2_supported = (f_7_EBX[5] & 1); + + cached = true; + is_supported = is_fma_supported && is_avx2_supported; + return is_supported; +} // end namespace AER } #endif diff --git a/src/simulators/statevector/qubitvector_avx2.cpp b/src/simulators/statevector/qubitvector_avx2.cpp index f99b17f384..28b504f1bd 100644 --- a/src/simulators/statevector/qubitvector_avx2.cpp +++ b/src/simulators/statevector/qubitvector_avx2.cpp @@ -19,6 +19,7 @@ #include "qubitvector_avx2.hpp" #include "qubitvector.hpp" +#include "qvintrin_avx.hpp" using namespace QV; diff --git a/src/simulators/statevector/qubitvector_avx2.hpp b/src/simulators/statevector/qubitvector_avx2.hpp index 3471572f1f..4dc8ff12b0 100755 --- a/src/simulators/statevector/qubitvector_avx2.hpp +++ b/src/simulators/statevector/qubitvector_avx2.hpp @@ -27,8 +27,7 @@ #include #include #include - -#include "qvintrin_avx.hpp" +#include namespace QV { diff --git a/src/simulators/statevector/qvintrin_avx.hpp b/src/simulators/statevector/qvintrin_avx.hpp index 7fc3af71eb..993adb430a 100644 --- a/src/simulators/statevector/qvintrin_avx.hpp +++ b/src/simulators/statevector/qvintrin_avx.hpp @@ -217,8 +217,6 @@ inline void reorder(QV::areg_t& qregs, QV::cvector_t& mat) { for(size_t i = 0; i < dim; ++i) { size_t index = 0U; for(size_t j = 0; j < N; ++j) { - - if(i & (1U << j)) index |= masks[j]; } @@ -719,7 +717,7 @@ void _apply_lambda(uint64_t data_size, const uint64_t skip, Lambda&& func, const std::sort(qubits_sorted.begin(), qubits_sorted.end()); #pragma omp parallel for if (omp_threads > 1) num_threads(omp_threads) - for (uint64_t k = 0; k < END; k += skip) { + for (int64_t k = 0; k < END; k += skip) { const auto inds = _indexes(qubits, qubits_sorted, k); std::forward < Lambda > (func)(inds, params); } diff --git a/src/simulators/statevector/statevector_state.hpp b/src/simulators/statevector/statevector_state.hpp index 55c6d0a48d..c0161cb30a 100755 --- a/src/simulators/statevector/statevector_state.hpp +++ b/src/simulators/statevector/statevector_state.hpp @@ -23,7 +23,6 @@ #include "framework/json.hpp" #include "simulators/state.hpp" #include "qubitvector.hpp" -#include "qubitvector_avx2.hpp" #ifdef AER_THRUST_SUPPORTED #include "qubitvector_thrust.hpp" #endif