commit
0cdfa8cd6b
@ -0,0 +1,57 @@
|
||||
/* 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. */
|
||||
|
||||
#include "paddle/utils/CpuId.h"
|
||||
#include "paddle/utils/Util.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
/// for MSVC
|
||||
#define CPUID(info, x) __cpuidex(info, x, 0)
|
||||
|
||||
#else
|
||||
|
||||
#include <cpuid.h>
|
||||
|
||||
/// for GCC/Clang
|
||||
#define CPUID(info, x) __cpuid_count(x, 0, info[0], info[1], info[2], info[3])
|
||||
|
||||
#endif
|
||||
|
||||
namespace paddle {
|
||||
|
||||
SIMDFlags::SIMDFlags() {
|
||||
unsigned int cpuInfo[4];
|
||||
// CPUID: https://en.wikipedia.org/wiki/CPUID
|
||||
CPUID(cpuInfo, 0x00000001);
|
||||
simd_flags_ |= cpuInfo[3] & (1 << 25) ? SIMD_SSE : SIMD_NONE;
|
||||
simd_flags_ |= cpuInfo[3] & (1 << 26) ? SIMD_SSE2 : SIMD_NONE;
|
||||
simd_flags_ |= cpuInfo[2] & (1 << 0) ? SIMD_SSE3 : SIMD_NONE;
|
||||
simd_flags_ |= cpuInfo[2] & (1 << 9) ? SIMD_SSSE3 : SIMD_NONE;
|
||||
simd_flags_ |= cpuInfo[2] & (1 << 19) ? SIMD_SSE41 : SIMD_NONE;
|
||||
simd_flags_ |= cpuInfo[2] & (1 << 20) ? SIMD_SSE42 : SIMD_NONE;
|
||||
simd_flags_ |= cpuInfo[2] & (1 << 12) ? SIMD_FMA3 : SIMD_NONE;
|
||||
simd_flags_ |= cpuInfo[2] & (1 << 28) ? SIMD_AVX : SIMD_NONE;
|
||||
|
||||
CPUID(cpuInfo, 0x00000007);
|
||||
simd_flags_ |= cpuInfo[1] & (1 << 5) ? SIMD_AVX2 : SIMD_NONE;
|
||||
simd_flags_ |= cpuInfo[1] & (1 << 16) ? SIMD_AVX512: SIMD_NONE;
|
||||
|
||||
CPUID(cpuInfo, 0x80000001);
|
||||
simd_flags_ |= cpuInfo[2] & (1 << 16) ? SIMD_FMA4 : SIMD_NONE;
|
||||
}
|
||||
|
||||
SIMDFlags* SIMDFlags::instance() {
|
||||
static SIMDFlags instance;
|
||||
return &instance;
|
||||
}
|
||||
|
||||
} // namespace paddle
|
@ -0,0 +1,71 @@
|
||||
/* 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
|
||||
|
||||
#include <iostream>
|
||||
#include "DisableCopy.h"
|
||||
|
||||
namespace paddle {
|
||||
|
||||
class SIMDFlags final {
|
||||
public:
|
||||
DISABLE_COPY(SIMDFlags);
|
||||
|
||||
SIMDFlags();
|
||||
|
||||
static SIMDFlags* instance();
|
||||
|
||||
inline bool isSSE() const { return simd_flags_ & SIMD_SSE; }
|
||||
inline bool isSSE2() const { return simd_flags_ & SIMD_SSE2; }
|
||||
inline bool isSSE3() const { return simd_flags_ & SIMD_SSE3; }
|
||||
inline bool isSSSE3() const { return simd_flags_ & SIMD_SSSE3; }
|
||||
inline bool isSSE41() const { return simd_flags_ & SIMD_SSE41; }
|
||||
inline bool isSSE42() const { return simd_flags_ & SIMD_SSE42; }
|
||||
inline bool isFMA3() const { return simd_flags_ & SIMD_FMA3; }
|
||||
inline bool isFMA4() const { return simd_flags_ & SIMD_FMA4; }
|
||||
inline bool isAVX() const { return simd_flags_ & SIMD_AVX; }
|
||||
inline bool isAVX2() const { return simd_flags_ & SIMD_AVX2; }
|
||||
inline bool isAVX512()const { return simd_flags_ & SIMD_AVX512;}
|
||||
|
||||
private:
|
||||
enum simd_t {
|
||||
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
|
||||
};
|
||||
|
||||
/// simd flags
|
||||
int simd_flags_ = SIMD_NONE;
|
||||
};
|
||||
|
||||
#define HAS_SSE SIMDFlags::instance()->isSSE()
|
||||
#define HAS_SSE2 SIMDFlags::instance()->isSSE2()
|
||||
#define HAS_SSE3 SIMDFlags::instance()->isSSE3()
|
||||
#define HAS_SSSE3 SIMDFlags::instance()->isSSSE3()
|
||||
#define HAS_SSE41 SIMDFlags::instance()->isSSE41()
|
||||
#define HAS_SSE42 SIMDFlags::instance()->isSSE42()
|
||||
#define HAS_FMA3 SIMDFlags::instance()->isFMA3()
|
||||
#define HAS_FMA4 SIMDFlags::instance()->isFMA4()
|
||||
#define HAS_AVX SIMDFlags::instance()->isAVX()
|
||||
#define HAS_AVX2 SIMDFlags::instance()->isAVX2()
|
||||
#define HAS_AVX512 SIMDFlags::instance()->isAVX512()
|
||||
|
||||
} // namespace paddle
|
@ -0,0 +1,52 @@
|
||||
/* 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. */
|
||||
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "paddle/utils/CpuId.h"
|
||||
#include "paddle/utils/Logging.h"
|
||||
#include "paddle/utils/Util.h"
|
||||
|
||||
using namespace paddle; // NOLINT
|
||||
|
||||
TEST(SIMDFlags, gccTest) {
|
||||
#if (defined(__GNUC__) || defined(__GNUG__)) && !(defined(__clang__))
|
||||
CHECK(!__builtin_cpu_supports("sse") != HAS_SSE);
|
||||
CHECK(!__builtin_cpu_supports("sse2") != HAS_SSE2);
|
||||
CHECK(!__builtin_cpu_supports("sse3") != HAS_SSE3);
|
||||
CHECK(!__builtin_cpu_supports("ssse3") != HAS_SSSE3);
|
||||
CHECK(!__builtin_cpu_supports("sse4.1")!= HAS_SSE41);
|
||||
CHECK(!__builtin_cpu_supports("sse4.2")!= HAS_SSE42);
|
||||
CHECK(!__builtin_cpu_supports("avx") != HAS_AVX);
|
||||
CHECK(!__builtin_cpu_supports("avx2") != HAS_AVX2);
|
||||
#endif
|
||||
}
|
||||
|
||||
TEST(SIMDFlags, normalPrint) {
|
||||
auto simd = SIMDFlags::instance();
|
||||
LOG(INFO) << "Has SSE2: " << std::boolalpha << simd->isSSE2();
|
||||
LOG(INFO) << "Has SSE3: " << std::boolalpha << simd->isSSE3();
|
||||
LOG(INFO) << "Has SSSE3: " << std::boolalpha << simd->isSSSE3();
|
||||
LOG(INFO) << "Has SSE4.1: " << std::boolalpha << simd->isSSE41();
|
||||
LOG(INFO) << "Has SSE4.2: " << std::boolalpha << simd->isSSE42();
|
||||
LOG(INFO) << "Has FMA3: " << std::boolalpha << simd->isFMA3();
|
||||
LOG(INFO) << "Has FMA4: " << std::boolalpha << simd->isFMA4();
|
||||
LOG(INFO) << "Has AVX: " << std::boolalpha << simd->isAVX();
|
||||
LOG(INFO) << "Has AVX2: " << std::boolalpha << simd->isAVX2();
|
||||
LOG(INFO) << "Has AVX512: " << std::boolalpha << simd->isAVX512();
|
||||
}
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
testing::InitGoogleTest(&argc, argv);
|
||||
paddle::initMain(argc, argv);
|
||||
return RUN_ALL_TESTS();
|
||||
}
|
Loading…
Reference in new issue