CpuId.h 3.6 KB
Newer Older
L
liaogang 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13
/* Copyright (c) 2016 PaddlePaddle Authors. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
    http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License. */

#pragma once

L
liaogang 已提交
14
#include "Common.h"
L
liaogang 已提交
15
#include "Error.h"
L
liaogang 已提交
16 17 18

namespace paddle {

19
// clang-format off
20
enum simd_t {
21 22 23 24 25 26 27 28 29 30 31 32
  SIMD_NONE   = 0,          ///< None
  SIMD_SSE    = 1 << 0,     ///< SSE
  SIMD_SSE2   = 1 << 1,     ///< SSE 2
  SIMD_SSE3   = 1 << 2,     ///< SSE 3
  SIMD_SSSE3  = 1 << 3,     ///< SSSE 3
  SIMD_SSE41  = 1 << 4,     ///< SSE 4.1
  SIMD_SSE42  = 1 << 5,     ///< SSE 4.2
  SIMD_FMA3   = 1 << 6,     ///< FMA 3
  SIMD_FMA4   = 1 << 7,     ///< FMA 4
  SIMD_AVX    = 1 << 8,     ///< AVX
  SIMD_AVX2   = 1 << 9,     ///< AVX 2
  SIMD_AVX512 = 1 << 10,    ///< AVX 512
33
  SIMD_NEON   = 1 << 11,    ///  NEON
34
};
35
// clang-format on
36

L
liaogang 已提交
37
class SIMDFlags final {
W
Wu Yi 已提交
38
 public:
Y
Yu Yang 已提交
39
  DISABLE_COPY(SIMDFlags);
L
liaogang 已提交
40

Y
Yu Yang 已提交
41
  SIMDFlags();
L
liaogang 已提交
42

43
  static SIMDFlags const* instance();
L
liaogang 已提交
44

45 46 47
  inline bool check(int flags) const {
    return !((simd_flags_ & flags) ^ flags);
  }
L
liaogang 已提交
48

W
Wu Yi 已提交
49
 private:
Y
Yu Yang 已提交
50
  int simd_flags_ = SIMD_NONE;
L
liaogang 已提交
51 52
};

53 54 55 56 57 58 59
/**
 * @brief   Check SIMD flags at runtime.
 *
 * For example.
 * @code{.cpp}
 *
 * if (HAS_SIMD(SIMD_AVX2 | SIMD_FMA4)) {
60
 *      avx2_fm4_stub();
61
 * } else if (HAS_SIMD(SIMD_AVX)) {
62
 *      avx_stub();
63 64 65 66
 * }
 *
 * @endcode
 */
67
#define HAS_SIMD(__flags) SIMDFlags::instance()->check(__flags)
68 69 70 71

/**
 * @brief   Check SIMD flags at runtime.
 *
72 73 74 75 76 77 78 79 80 81 82 83 84 85 86
 * 1. Check all SIMD flags at runtime:
 *
 * @code{.cpp}
 * if (HAS_AVX && HAS_AVX2) {
 *      avx2_stub();
 * }
 * @endcod
 *
 * 2. Check one SIMD flag at runtime:
 *
 * @code{.cpp}
 * if (HAS_SSE41 || HAS_SSE42) {
 *      sse4_stub();
 * }
 * @endcode
87
 */
88 89 90 91 92 93 94 95 96 97 98 99
// clang-format off
#define HAS_SSE     HAS_SIMD(SIMD_SSE)
#define HAS_SSE2    HAS_SIMD(SIMD_SSE2)
#define HAS_SSE3    HAS_SIMD(SIMD_SSE3)
#define HAS_SSSE3   HAS_SIMD(SIMD_SSSE3)
#define HAS_SSE41   HAS_SIMD(SIMD_SSE41)
#define HAS_SSE42   HAS_SIMD(SIMD_SSE42)
#define HAS_FMA3    HAS_SIMD(SIMD_FMA3)
#define HAS_FMA4    HAS_SIMD(SIMD_FMA4)
#define HAS_AVX     HAS_SIMD(SIMD_AVX)
#define HAS_AVX2    HAS_SIMD(SIMD_AVX2)
#define HAS_AVX512  HAS_SIMD(SIMD_AVX512)
100
#define HAS_NEON    HAS_SIMD(SIMD_NEON)
101
// clang-format on
L
liaogang 已提交
102

103 104 105 106 107 108 109 110 111 112 113 114 115 116 117
/**
 * Invoke checkCPUFeature() before Paddle initialization to
 * check target machine whether support compiled instructions.
 * If not, simply throw out an error.
 */
inline Error __must_check checkCPUFeature() {
  Error err;
#ifndef __AVX__
  if (HAS_AVX) {
    LOG(WARNING) << "PaddlePaddle wasn't compiled to use avx instructions, "
                 << "but these are available on your machine and could "
                 << "speed up CPU computations via CMAKE .. -DWITH_AVX=ON";
  }
#else
  if (!HAS_AVX) {
L
liaogang 已提交
118
    err = Error(
119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135
        "PaddlePaddle was compiled to use avx instructions, "
        "but these aren't available on your machine, please "
        "disable it via CMAKE .. -DWITH_AVX=OFF");
  }
#endif  // __AVX__
#ifdef __SSE3__
  if (!HAS_SSE3) {
    err = Error(
        "PaddlePaddle was compiled to use sse3 instructions, "
        "which is the minimum requirement of PaddlePaddle. "
        "But these aren't available on your current machine.");
  }
#endif  // __SSE3__

  return err;
}

Y
Yu Yang 已提交
136
}  // namespace paddle