LDP X8, X2, [X0, #0x10]!
Run Code Online (Sandbox Code Playgroud)
有关将A32 PUSH/POP指令移植到A64中的文档还提供了以下示例:
PUSH {r0-r1} ---> STP X0, X1, [SP, #-16]!
POP {r0-r1} ---> LDP X0, X1, [SP], #16
Run Code Online (Sandbox Code Playgroud)
这两个页面都没有解释说明书末尾的感叹号是什么意思.它是什么?
有没有办法水平异步AVX寄存器 - 具体来说,对256位寄存器的四个64位组件进行异或?
目标是获得AVX寄存器的所有4个64位组件的XOR.它基本上与水平add(_mm256_hadd_epi32())做同样的事情,除了我想要XOR而不是ADD.
标量代码是:
inline uint64_t HorizontalXor(__m256i t) {
return t.m256i_u64[0] ^ t.m256i_u64[1] ^ t.m256i_u64[2] ^ t.m256i_u64[3];
}
Run Code Online (Sandbox Code Playgroud) __m256d _mm256_log2_pd (__m256d a)除了英特尔之外,SVML 还没有其他编译器可用,他们表示其性能在AMD处理器上是有缺陷的.在g ++ - 4.8中缺少AVX日志内在函数(_mm256_log_ps)中的一些互联网实现?和SSE和AVX的SIMD数学库,但它们似乎比AVX2更多的SSE.还有Agner Fog的矢量库,但是它是一个包含更多东西的大型库,它只是向量log2,所以从它的实现中很难找出向量log2操作的基本部分.
那么有人可以解释如何有效地实现log2()4个double数字向量的操作吗?即就是__m256d _mm256_log2_pd (__m256d a)这样,但可用于其他编译器,并且AMD和Intel处理器的效率相当高.
编辑:在我目前的特定情况下,数字是介于0和1之间的概率,而对数用于熵计算:所有i的和的否定P[i]*log(P[i]).浮点指数的P[i]范围很大,因此数字可以接近0.我不确定准确度,因此会考虑以30位尾数开头的任何解决方案,尤其是可调整的解决方案.
EDIT2:这是我到目前为止的实现,基于https://en.wikipedia.org/wiki/Logarithm#Power_series的 "更有效的系列" .怎么改进?(需要提高性能和精度)
namespace {
const __m256i gDoubleExpMask = _mm256_set1_epi64x(0x7ffULL << 52);
const __m256i gDoubleExp0 = _mm256_set1_epi64x(1023ULL << 52);
const __m256i gTo32bitExp = _mm256_set_epi32(0, 0, 0, 0, 6, 4, 2, 0);
const __m128i gExpNormalizer = _mm_set1_epi32(1023);
//TODO: some 128-bit variable or two 64-bit variables …Run Code Online (Sandbox Code Playgroud) 考虑N线程执行一些具有小结果值的异步任务,如double或int64_t.因此,8结果值可以适合单个CPU缓存行.N等于CPU核心数.
一方面,如果我只是分配一个N项目数组,每个a double或者int64_t,那么8 线程将共享一个CPU缓存行,这似乎效率低下.
另一方面,如果我为每个double/ 分配一个完整的缓存行int64_t,接收器线程将必须获取N缓存行,每个缓存行由不同的CPU核心(1除外)写入.
那么这种情况是否有效的解决方案?CPU是x86-64.C++中的解决方案是首选.
澄清1:线程启动/退出开销不大,因为使用了线程池.所以它主要是关键部分的同步.
澄清2:并行批次具有依赖性.主线程只能在收集并处理上一批次的结果后才能启动下一批并行计算.因为前一批次的结果用作下一批次的一些参数.
我正在perfUbuntu 20.04 上进行分析(尽管我可以使用任何其他免费工具)。它允许在 CLI 中传递延迟,以便事件收集在程序启动后的某个时间后开始。然而,这个时间变化很大(1000 秒中有 20 秒),并且有一些我也不感兴趣的尾部计算。
因此,最好从我的程序中调用一些 API 来启动perf我感兴趣的代码片段的事件收集,然后在代码完成后停止收集。
在循环中运行代码并不是真正的选择,因为有大约 30 秒的初始化阶段和 10 秒的测量阶段,我只对后者感兴趣。
为了确定由相对路径指定的文件的规范路径或包含\..\在中间的路径,stackoverflow建议使用GetFullPathName()此处或GetLongPathName()此处.
这些功能有什么区别?
目的是从相对路径(如..\someDir\someFile.txt和someOtherDir\someFile.txt)获取以驱动器号开头的路径,并\..\从路径中消除额外的路径(如C:\dirA\dirB\..\someFile.txt- > C:\dirA\someFile.txt).
在某些内在函数中,它们使用后缀,x如_mm256_set1_epi64x. 它的意义是什么?作为参考,_mm256_set1_epi32没有这个后缀。
是否有一种内在或另一种有效的方法将AVX寄存器的64位组件的高/低32位组件重新打包到SSE寄存器中?使用AVX2的解决方案还可以.
到目前为止,我正在使用以下代码,但是分析器说它在Ryzen 1800X上很慢:
// Global constant
const __m256i gHigh32Permute = _mm256_set_epi32(0, 0, 0, 0, 7, 5, 3, 1);
// ...
// function code
__m256i x = /* computed here */;
const __m128i high32 = _mm256_castsi256_si128(_mm256_permutevar8x32_epi32(x),
gHigh32Permute); // This seems to take 3 cycles
Run Code Online (Sandbox Code Playgroud) 考虑随机生成的__m256i向量.是否有更快的精确方法将它们转换为(包含)和(仅)__m256之间的浮动向量而不是除以?01float(1ull<<32)
这是我到目前为止所尝试的,iRand输入在哪里,ans是输出:
const __m256 fRand = _mm256_cvtepi32_ps(iRand);
const __m256 normalized = _mm256_div_ps(fRand, _mm256_set1_ps(float(1ull<<32)));
const __m256 ans = _mm256_add_ps(normalized, _mm256_set1_ps(0.5f));
Run Code Online (Sandbox Code Playgroud) 我试图perf在 Ubuntu 20.04 上进行配置,但问题是许多函数没有出现在其中(可能是因为它们是内联的),或者只出现它们的地址(没有名称等)。我正在使用 CMake 的RelWithDebInfo构建。但有一些模板函数我不知道如何将其引入分析器结果中。我认为noinline如果这在 C++ 中对于模板函数是合法的,那么标记它们可能会有所帮助,但这会破坏代码库并且需要针对每个函数完成。有什么建议如何noinline同时实现所有功能吗?