106 lines
3.3 KiB
C++
106 lines
3.3 KiB
C++
// Copyright (c) 2010-2025, Lawrence Livermore National Security, LLC. Produced
|
|
// at the Lawrence Livermore National Laboratory. All Rights reserved. See files
|
|
// LICENSE and NOTICE for details. LLNL-CODE-806117.
|
|
//
|
|
// This file is part of the MFEM library. For more information and source code
|
|
// availability visit https://mfem.org.
|
|
//
|
|
// MFEM is free software; you can redistribute it and/or modify it under the
|
|
// terms of the BSD-3 license. We welcome feedback and contributions, see file
|
|
// CONTRIBUTING.md for details.
|
|
|
|
#ifndef MFEM_SIMD_HPP
|
|
#define MFEM_SIMD_HPP
|
|
|
|
#include "../config/tconfig.hpp"
|
|
|
|
// --- AutoSIMD + specializations with intrinsics
|
|
#include "simd/auto.hpp"
|
|
#ifdef MFEM_USE_SIMD
|
|
#if defined(__aarch64__) && defined(__ARM_FEATURE_SVE)
|
|
#include "simd/sve.hpp"
|
|
#elif defined(__VSX__)
|
|
#include "simd/vsx.hpp"
|
|
#elif defined (__bgq__)
|
|
#include "simd/qpx.hpp"
|
|
#elif defined(__x86_64__) || defined(_M_X64) || defined(_M_IX86)
|
|
#include "simd/x86.hpp"
|
|
#elif !defined(_MSC_VER)
|
|
#warning Unknown SIMD architecture
|
|
#else
|
|
#pragma message("warning: Unknown SIMD architecture")
|
|
#endif
|
|
#endif
|
|
|
|
// MFEM_SIMD_BYTES is the default SIMD size used by MFEM, see e.g. class
|
|
// TBilinearForm and the default traits class AutoSIMDTraits.
|
|
// MFEM_ALIGN_BYTES determines the padding used in TVector when its 'align'
|
|
// template parameter is set to true -- it ensures that the size of such TVector
|
|
// types is a multiple of MFEM_ALIGN_BYTES. MFEM_ALIGN_BYTES must be a multiple
|
|
// of MFEM_SIMD_BYTES.
|
|
#if !defined(MFEM_USE_SIMD)
|
|
#define MFEM_SIMD_BYTES 8
|
|
#define MFEM_ALIGN_BYTES 32
|
|
#elif defined(__AVX512F__)
|
|
#define MFEM_SIMD_BYTES 64
|
|
#define MFEM_ALIGN_BYTES 64
|
|
#elif defined(__aarch64__) && defined(__ARM_FEATURE_SVE)
|
|
#define MFEM_SIMD_BYTES 64
|
|
#define MFEM_ALIGN_BYTES 64
|
|
#elif defined(__AVX__) || defined(__VECTOR4DOUBLE__)
|
|
#define MFEM_SIMD_BYTES 32
|
|
#define MFEM_ALIGN_BYTES 32
|
|
#elif defined(__SSE2__) || defined(__VSX__)
|
|
#define MFEM_SIMD_BYTES 16
|
|
#define MFEM_ALIGN_BYTES 32
|
|
#else
|
|
#define MFEM_SIMD_BYTES 8
|
|
#define MFEM_ALIGN_BYTES 32
|
|
#endif
|
|
|
|
// derived macros
|
|
#define MFEM_ROUNDUP(val,base) ((((val)+(base)-1)/(base))*(base))
|
|
#define MFEM_ALIGN_SIZE(size,type) \
|
|
MFEM_ROUNDUP(size,(MFEM_ALIGN_BYTES)/sizeof(type))
|
|
|
|
namespace mfem
|
|
{
|
|
|
|
template<typename complex_t, typename real_t>
|
|
struct AutoSIMDTraits
|
|
{
|
|
static const int block_size = MFEM_TEMPLATE_BLOCK_SIZE;
|
|
|
|
// Alignment for arrays of vcomplex_t and vreal_t
|
|
static const int align_bytes = MFEM_SIMD_BYTES;
|
|
|
|
static const int batch_size = 1;
|
|
|
|
static const int simd_size = MFEM_SIMD_BYTES/sizeof(real_t);
|
|
|
|
typedef AutoSIMD<complex_t, simd_size, MFEM_SIMD_BYTES> vcomplex_t;
|
|
typedef AutoSIMD<real_t, simd_size, MFEM_SIMD_BYTES> vreal_t;
|
|
typedef AutoSIMD<int, simd_size, simd_size*sizeof(int)> vint_t;
|
|
};
|
|
|
|
template<typename complex_t, typename real_t>
|
|
struct NoSIMDTraits
|
|
{
|
|
static const int block_size = MFEM_TEMPLATE_BLOCK_SIZE;
|
|
|
|
// Alignment for arrays of vcomplex_t and vreal_t
|
|
static const int align_bytes = sizeof(real_t);
|
|
|
|
static const int batch_size = 1;
|
|
|
|
static const int simd_size = 1;
|
|
|
|
typedef AutoSIMD<complex_t, simd_size, align_bytes> vcomplex_t;
|
|
typedef AutoSIMD<real_t, simd_size, align_bytes> vreal_t;
|
|
typedef AutoSIMD<int, simd_size, simd_size*sizeof(int)> vint_t;
|
|
};
|
|
|
|
} // mfem namespace
|
|
|
|
#endif // MFEM_SIMD_HPP
|