我是AVX的新手(来自ARM NEON),并且令人不快地惊讶于AVX缺少许多U8算术,绝对差异在于他们之间缺失.
因此我不得不求助于max(a,b)-min(a,b)内联函数:
static inline __m256i _mm256_abd_epu8(__m256i a, __m256i b)
{
return _mm256_sub_epi8(_mm256_max_epu8(a, b), _mm256_min_epu8(a, b));
}
Run Code Online (Sandbox Code Playgroud)
我很好奇是否有更有效的方法来处理这个问题.
是的,我知道_mm256_sad_epu8,但我需要自己的差异,而不是总和.
我很感激任何输入,并且没关系AVX2任何向后兼容性.
提前致谢.
假设以AVX2为目标的编译和C++内在函数,如果我每个体体计算使用17个寄存器编写一个nbody算法,那么第17个寄存器可以间接(寄存器重命名硬件)或直接(visual studio编译器,gcc编译器)映射到AVX上-512注册以减少内存依赖关闭?例如,skylake架构有1或2个AVX-512 fma单元.这个数字是否也改变了总寄存器?(具体来说,至强银4114 cpu)
如果这样可行,它是如何工作的?当所有指令都是AVX2或更低时,第一个硬件线程使用每个ZMM向量的前半部分和第二个硬件线程使用每个ZMM向量的后半部分?
编辑:如果在目标机器上进行在线编译会怎样(例如,使用OpenCL)?司机可以为我注册使用吗?
x86 cpu-architecture cpu-registers compiler-optimization avx512
在 avx 指令中用作源的寄存器何时可以在指令开始处理后重用?
例如:我想使用vgatherdps消耗两个 ymm 寄存器的指令,其中之一是位移索引。我意识到vgatherdps收集数据需要花费大量时间,因为数据的局部性较差。
位移索引寄存器是否会在指令执行期间被保留,或者我可以在后续指令中重用它而无需挂起管道?
我想知道为什么像这样的简单循环无法达到我的 CPU 时钟速度(4,2Ghz):
float sum = 0;
for (int i = 0; i < 1000000; i+=1) {
sum = sum * 1 + 1;
}
Run Code Online (Sandbox Code Playgroud)
凭直觉,我希望在不到 1 毫秒(例如 0,238 毫秒)的时间内实现这一目标,每秒进行 42 亿次迭代。但我得到的时间约为 3 毫秒,即每秒约 3.33 亿次迭代。
我假设做数学运算需要 2 个周期,一个用于乘法,另一个用于求和。假设我正在执行 6.66 亿次操作……看起来仍然很慢。然后我假设循环比较需要一个周期,循环计数器需要另一个周期......
所以我创建了以下代码来删除循环......
void listOfSums() {
float internalSum = 0;
internalSum = internalSum * 1 + 1;
internalSum = internalSum * 1 + 1;
internalSum = internalSum * 1 + 1;
internalSum = internalSum * 1 + 1;
// Repeated 100k …Run Code Online (Sandbox Code Playgroud) 我读到gprof(函数分析)和其他分析方法可以返回执行程序时发生的浮点运算的数量,因此想知道Flops如何比常规运算贵得多?
是它更快地通过的装置计算两个向量的点积dpps指令形式SSE 4.1指令集或通过使用一系列的addps,shufps并mulps从SSE 1?
我试图使用SIMD指令加速我的C代码中的点积计算.但是,我的函数的运行时间大致相等.如果有人能解释为什么以及如何加快计算,那就太棒了.
具体来说,我正在尝试计算两个数组的点积,其中包含大约10,000个元素.我的常规C函数如下:
float my_dotProd( float const * const x, float const * const y, size_t const N ){
// N is the number of elements in the arrays
size_t i;
float out=0;
for( i=0; i < N; ++i ){
out += x[i] * y[i];
}
return out;
}
Run Code Online (Sandbox Code Playgroud)
我使用AVX SIMD命令的功能如下:
void my_malloc( size_t nBytes, void ** ptrPtr ){
int boundary = 32;
posix_memalign( ptrPtr, boundary, nBytes );
}
float cimpl_sum_m128( __m128 x ){
float out;
__m128 sum = x;
sum …Run Code Online (Sandbox Code Playgroud) 我在SSE2和AVX中实现了4x4矩阵逆.两者都比普通实现更快.但是如果启用AVX(-mavx),则SSE2实现比手动AVX实现运行得更快.似乎编译器使我的SSE2实现与AVX更友好:(
在我的AVX实现中,乘法次数减少,添加次数减少......所以我希望AVX可以比SSE更快.也许有些像说明资讯_mm256_permute2f128_ps,_mm256_permutevar_ps/_mm256_permute_ps使得AVX慢?我不是要将SSE/XMM寄存器加载到AVX/YMM寄存器.
如何使我的AVX实现比SSE更快?
我的CPU:Intel(R)Core(TM)i7-3615QM CPU @ 2.30GHz(Ivy Bridge)
Plain with -O3 : 0.045853 secs
SSE2 with -O3 : 0.026021 secs
SSE2 with -O3 -mavx: 0.024336 secs
AVX1 with -O3 -mavx: 0.031798 secs
Updated (See bottom of question) all have -O3 -mavx flags:
AVX1 (reduced div) : 0.027666 secs
AVX1 (using rcp_ps) : 0.023205 secs
SSE2 (using rcp_ps) : 0.021969 secs
Run Code Online (Sandbox Code Playgroud)
初始矩阵:
Matrix (float4x4):
|0.0714 -0.6589 0.7488 2.0000|
|0.9446 0.2857 0.1613 4.0000|
|-0.3202 0.6958 0.6429 6.0000|
|0.0000 …Run Code Online (Sandbox Code Playgroud) 这是在合并流水线和您需要的必要NOP时实现mov和通过x86添加的正确方法.
mov $10, eax
NOP
NOP
NOP
add $2, eax
Run Code Online (Sandbox Code Playgroud)
如果我想用mov更改eax,我可以立即用另一个mov覆盖它,因为你只是覆盖已经存在的内容,或者我是否需要再次写3个NOP才能完成WMEDF循环?
mov $10, eax
mov $12, eax
Run Code Online (Sandbox Code Playgroud)
要么
mov $10, eax
NOP
NOP
NOP
mov $12, eax
Run Code Online (Sandbox Code Playgroud) 根据我的阅读,IA-32架构有10个32位和6个16位寄存器.
32位寄存器如下:
16位寄存器如下:
但是,我找不到有关当前指令寄存器(CIR)或存储器缓冲寄存器(MBR)/存储器数据寄存器(MBR)的任何信息.这些寄存器是否被称为其他东西?这些寄存器是32位吗?
我假设它们是32位的,并且在这种架构下最常用的指令长度不超过4个字节.从观察来看,许多指令似乎都在4个字节以下,例如:
对于更长的指令,CPU将使用前缀代码和其他可选代码.较长的指令需要多个周期才能完成,这取决于指令长度.
我是否正确,因为有问题的寄存器长度为32位?IA-32架构中是否还有其他寄存器,我也应该注意这些寄存器?