有趣的是它在游戏和其他软件中的工作原理。
更准确地说,我正在寻求一个解决方案C++。
就像是:
if AMX available -> Use AMX version of the math library
else if AVX-512 available -> Use AVX-512 version of the math library
else if AVX-256 available -> Use AVX-256 version of the math library
etc.
Run Code Online (Sandbox Code Playgroud)
我的基本想法是在不同的 DLL 中编译库并在运行时交换它们,但这对我来说似乎不是最好的解决方案。
我有一个循环将两个float*数组加载到__m256向量中并处理它们。在这个循环之后,我有代码将平衡值加载到向量中,然后处理它们。所以函数上没有对齐要求。
以下是将数据余额加载到向量中的代码:
size_t constexpr FLOATS_IN_M128 = sizeof(__m128) / sizeof(float);
size_t constexpr FLOATS_IN_M256 = FLOATS_IN_M128 * 2;
Run Code Online (Sandbox Code Playgroud)
...
assert(bal < FLOATS_IN_M256);
float ary[FLOATS_IN_M256 * 2];
auto v256f_q = _mm256_setzero_ps();
_mm256_storeu_ps(ary, v256f_q);
_mm256_storeu_ps(&ary[FLOATS_IN_M256], v256f_q);
float *dest = ary;
size_t offset{};
while (bal--)
{
dest[offset] = p_q_n[pos];
dest[offset + FLOATS_IN_M256] = p_val_n[pos];
offset++;
pos++;
}
// the two vectors that will be processed
v256f_q = _mm256_loadu_ps(ary);
v256f_val = _mm256_loadu_ps(&ary[FLOATS_IN_M256]);
Run Code Online (Sandbox Code Playgroud)
assert(bal < FLOATS_IN_M256);当我使用编译器资源管理器时,设置为“x86-64 clang 16.0.0 -march=x86-64-v3 -O3”,编译器会在该行存在时展开循环。但是,assert()在模式中被忽略 …
我正在尝试在一些文件上实现和编码,其中一些包含 SIMD 调用。我已经在服务器上编译了这段代码,运行与我的机器基本相同的操作系统,但我无法编译它。
\n\n这是错误:
\n\nmake\ng++ main.cpp -march=native -o main -fopenmp\nIn file included from /usr/lib/gcc/x86_64-linux-gnu/7/include/immintrin.h:53:0,\n from tensor.hpp:9,\n from main.cpp:4:\n/usr/lib/gcc/x86_64-linux-gnu/7/include/avx512vlintrin.h: In function \xe2\x80\x98_ZN6TensorIdE8add_avx2ERKS0_._omp_fn.5\xe2\x80\x99:\n/usr/lib/gcc/x86_64-linux-gnu/7/include/avx512vlintrin.h:447:1: error: inlining failed in call to always_inline \xe2\x80\x98__m256d _mm256_mask_add_pd(__m256d, __mmask8, __m256d, __m256d)\xe2\x80\x99: target specific option mismatch\n _mm256_mask_add_pd (__m256d __W, __mmask8 __U, __m256d __A,\n ^~~~~~~~~~~~~~~~~~\nIn file included from main.cpp:4:0:\ntensor.hpp:228:33: note: called from here\n res = _mm256_mask_add_pd(tmp, 0xFF, _mm256_mask_loadu_pd(tmp, 0xFF, &elements[i]), _mm256_mask_loadu_pd(tmp, 0xFF, &a.elements[i]));\n ~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\nIn file included from /usr/lib/gcc/x86_64-linux-gnu/7/include/immintrin.h:53:0,\n from tensor.hpp:9,\n from main.cpp:4:\n/usr/lib/gcc/x86_64-linux-gnu/7/include/avx512vlintrin.h:610:1: error: inlining failed in call to …Run Code Online (Sandbox Code Playgroud) 英特尔的内在指南列出了内在的_mm256_loadu_epi32:
_m256i _mm256_loadu_epi32 (void const* mem_addr);
/*
Instruction: vmovdqu32 ymm, m256
CPUID Flags: AVX512VL + AVX512F
Description
Load 256-bits (composed of 8 packed 32-bit integers) from memory into dst.
mem_addr does not need to be aligned on any particular boundary.
Operation
a[255:0] := MEM[mem_addr+255:mem_addr]
dst[MAX:256] := 0
*/
Run Code Online (Sandbox Code Playgroud)
但是 clang 和 gcc 不提供这种内在的。相反,他们avx512vlintrin.h仅提供(在文件中)屏蔽版本
_mm256_mask_loadu_epi32 (__m256i, __mmask8, void const *);
_mm256_maskz_loadu_epi32 (__mmask8, void const *);
Run Code Online (Sandbox Code Playgroud)
归结为相同的指令vmovdqu32。我的问题:我怎样才能模仿_mm256_loadu_epi32:
inline _m256i _mm256_loadu_epi32(void const* mem_addr)
{
/* …Run Code Online (Sandbox Code Playgroud) 我在 C/C++ 代码中明确使用了英特尔 SIMD 内在扩展。为了编译代码,我需要在命令行上指定 -mavx、-mavx512 或类似的内容。我对这一切都很满意。
然而,从阅读 gcc 手册页来看,并不清楚这些命令行标志是否也告诉 gcc 编译器尝试使用英特尔 SIMD 指令自动矢量化 C/C++ 代码。有人知道情况是否如此吗?-mavx 标志只是允许您手动将 SIMD 内在函数插入代码中,还是还告诉编译器在编译 C/C++ 代码时使用 SIMD 指令?
我编写了一些代码,并使用 gcc 和本机架构选项对其进行了编译。
通常,我可以使用此代码并在没有 AVX2(仅 AVX)的旧计算机上运行它,并且它工作正常。然而,编译器似乎实际上正在发出 AVX2 指令(终于!),而不是我需要自己包含 SIMD 内在函数。
我想修改程序,以便支持两种途径(AVX2 和非 AVX2)。换句话说,我想要以下伪代码。
if (AVX2){
callAVX2Version();
}else if (AVX){
callAVXVersion();
}else{
callSSEVersion();
}
void callAVX2Version(){
#pragma gcc -mavx2
}
void callAVXVersion(){
#pragma gcc -mavx
}
Run Code Online (Sandbox Code Playgroud)
我知道如何执行运行时检测部分,我的问题是是否可以执行功能特定的 SIMD 选择部分。
英特尔C++编译器和/或GCC是否支持以下内在函数,例如自2012/2013年以来MSVC的内在函数?
int _rdrand16_step(uint16_t*);
int _rdrand32_step(uint32_t*);
int _rdrand64_step(uint64_t*);
int _rdseed16_step(uint16_t*);
int _rdseed32_step(uint32_t*);
int _rdseed64_step(uint64_t*);
Run Code Online (Sandbox Code Playgroud)
如果支持这些内在函数,那么它们支持哪个版本(请使用编译时常量)?
我正在运行带有 SIMD 指令的 C 代码来测试我的环境。我在 Codeblocks 和 Windows 10 中运行它
#include <immintrin.h>
#include <stdio.h>
#define ARRAY_LENGTH 8
int main(int argc, char* argv[]) {
__m256i first = _mm256_set_epi32(10, 20, 30, 40, 50, 60, 70, 80);
__m256i second = _mm256_set_epi32(5, 5, 5, 5, 5, 5, 5, 5);
__m256i result = _mm256_add_epi32(first, second);
int* values = (int*) &result;
for (
unsigned short i = 0;
i < ARRAY_LENGTH;
i += 1
) {
printf("%d ", values[i]);
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
这段代码抛出一个错误,我无法修复它。
error: inlining …Run Code Online (Sandbox Code Playgroud) 考虑以下计算 i32 数组总和的示例:
示例1:简单的for循环
pub fn vec_sum_for_loop_i32(src: &[i32]) -> i32 {
let mut sum = 0;
for c in src {
sum += *c;
}
sum
}
Run Code Online (Sandbox Code Playgroud)
示例 2:显式 SIMD 求和:
use std::arch::x86_64::*;
// #[inline]
pub fn vec_sum_simd_direct_loop(src: &[i32]) -> i32 {
#[cfg(debug_assertions)]
assert!(src.as_ptr() as u64 % 64 == 0);
#[cfg(debug_assertions)]
assert!(src.len() % (std::mem::size_of::<__m256i>() / std::mem::size_of::<i32>()) == 0);
let p_src = src.as_ptr();
let batch_size = std::mem::size_of::<__m256i>() / std::mem::size_of::<i32>();
#[cfg(debug_assertions)]
assert!(src.len() % batch_size == 0);
let result: i32;
unsafe {
let …Run Code Online (Sandbox Code Playgroud) 我正在尝试学习AVX指令,并且在运行我收到的基本代码时
非法指令(核心已转储)
该代码在下面提到,我正在使用它进行编译
g ++ -mavx512f 1.cpp
问题到底是什么?如何解决?谢谢!
#include <immintrin.h>
#include<iostream>
using namespace std;
void add(const float a[], const float b[], float res[], int n)
{
int i = 0;
for(; i < (n&(~0x31)) ; i+=32 )
{
__m512 x = _mm512_loadu_ps( &a[i] );
__m512 y = _mm512_loadu_ps( &b[i] );
__m512 z = _mm512_add_ps(x,y);
_mm512_stream_ps(&res[i],z);
}
for(; i<n; i++) res[i] = a[i] + b[i];
}
int main()
{
int n = 100000;
float a[n], b[n], res[n];
for(int i = 0;i …Run Code Online (Sandbox Code Playgroud) C++ 不允许 constexpr 内联汇编有充分的理由吗?为什么 C++20 中允许未计算的内联汇编表达式?