小编ale*_*cco的帖子

您知道哪些技术可以避免条件分支?

有时CPU占用大部分时间的循环经常会有一些分支预测错误(错误预测)(接近0.5概率).我在非常孤立的线程上看到了一些技术但从未列出过.我所知道的那些已经解决了条件可以变为bool并且以某种方式使用0/1来改变的情况.是否有其他可以避免的条件分支?

例如(伪代码)

loop () {
  if (in[i] < C )
    out[o++] = in[i++]
  ...
}
Run Code Online (Sandbox Code Playgroud)

可以用这样的东西重写,可能会失去一些可读性:

loop() {
  out[o] = in[i]  // copy anyway, just don't increment
  inc = in[i] < C  // increment counters? (0 or 1)
  o += inc
  i += inc
}
Run Code Online (Sandbox Code Playgroud)

此外,我已经看到在野外的技术在某些情况下在有条件的情况下改变&&,&现在正在逃避我的思想.我是这个优化级别的新手,但确实感觉还有更多.

c optimization assembly

22
推荐指数
5
解决办法
1万
查看次数

GCC 4.4:避免在gcc中对switch/case语句进行范围检查?

这只是4.4之前的GCC版本的问题,这在GCC 4.5中已得到修复.

是否有可能告诉编译器交换机中使用的变量是否适合所提供的case语句?特别是如果它是一个小范围并且有一个跳转表生成.

extern int a;
main()
{
        switch (a & 0x7) {   // 0x7  == 111  values are 0-7
        case 0: f0(); break;
        case 1: f1(); break;
        case 2: f2(); break;
        case 3: f3(); break;
        case 4: f4(); break;
        case 5: f5(); break;
        case 6: f6(); break;
        case 7: f7(); break;
        }
}
Run Code Online (Sandbox Code Playgroud)

我尝试xor'ing到低位(作为例子),使用枚举,使用gcc_unreachable()无济于事.生成的代码总是检查变量是否在范围内,添加无条件分支条件并移走跳转表计算代码.

注意:这是在解码器的最内层循环中,性能非常重要.

看来我不是唯一 一个.

没有办法告诉gcc永远不会采用默认分支,尽管它可以省略默认分支,如果它可以证明该值永远不会超出先前的条件检查范围.

那么,你如何帮助gcc证明变量适合并且上面的例子中没有默认分支?(当然,不添加条件分支.)

更新

  1. 这是在OS X 10.6 Snow Leopard上使用GCC 4.2(默认来自Xcode.)它没有发生在Linux中的GCC 4.4/4.3(由Nathon和Jens Gustedt报道).

  2. 示例中的函数是为了可读性,认为这些是内联的或只是语句.在x86上进行函数调用是很昂贵的.

    此外,如注释中所述,该示例属于数据循环(大数据).

    使用gcc 4.2/OS X生成的代码是:

    [...]
    andl    $7, %eax …
    Run Code Online (Sandbox Code Playgroud)

c assembly switch-statement gcc4.4

15
推荐指数
2
解决办法
3090
查看次数

将32位解压缩为32字节SIMD向量的最快方法

将32位存储在uint32_t内存中,将每个位解压缩到AVX寄存器的单独字节元素的最快方法是什么?这些位可以位于各自字节内的任何位置.

编辑:澄清,我的意思是位0进入字节0,位1到字节1.显然,字节内的所有其他位都为零.我现在最好的是2 PSHUFB并且每个位置都有一个掩码寄存器.

如果uint32_t是位图,则相应的向量元素应为0或非0.(即我们可以得到一个矢量掩码,其中vpcmpeqb一个矢量为全零的矢量).

https://software.intel.com/en-us/forums/topic/283382

x86 simd avx avx2

7
推荐指数
1
解决办法
2202
查看次数

快速注册时的字节数?

给定4个字节的寄存器(或SIMD的16个寄存器),必须有一种有效的方法来使用一些指令对寄存器中的字节进行排序.

提前致谢.

sorting assembly simd

6
推荐指数
2
解决办法
1877
查看次数

在SSE2/SSSE3上转换8个16位元素寄存器

(我是SSE/asm的新手,如果这显而易见或多余则道歉)

是否有更好的方法来转换包含16位值的8个SSE寄存器,而不是执行24个unpck [lh] ps和8/16 + shuffle以及使用8个额外的寄存器?(注意最多使用SSSE 3指令,Intel Merom,又称SSE4缺少BLEND*.)

假设你有寄存器v [0-7]并使用t0-t7作为辅助寄存器.在伪内在函数代码中:

/* Phase 1: process lower parts of the registers */
/* Level 1: work first part of the vectors */
/*   v[0]  A0 A1 A2 A3 A4 A5 A6 A7
**   v[1]  B0 B1 B2 B3 B4 B5 B6 B7
**   v[2]  C0 C1 C2 C3 C4 C5 C6 C7
**   v[3]  D0 D1 D2 D3 D4 D5 D6 D7
**   v[4]  E0 E1 E2 E3 E4 E5 E6 E7 …
Run Code Online (Sandbox Code Playgroud)

x86 assembly sse simd matrix

6
推荐指数
2
解决办法
3310
查看次数

将2个未对齐的64位值加载到带SSSE3的sse寄存器中的最佳方法是什么?

有2个指向2个未对齐的8字节块的指针要加载到xmm寄存器中.如果可能,使用内在函数.如果可能,不使用辅助寄存器.没有pinrd.(SSSE Core 2)

sse simd intrinsics

6
推荐指数
1
解决办法
1824
查看次数

AVX中的AVX2 VPSHUFB仿真

在AVX中,只有128位 PSHUFB

VPSHUFB xmm1, xmm2, xmm3/m128
Run Code Online (Sandbox Code Playgroud)

只有AVX2 PSHUFB才能满足整个256位AVX寄存器的要求

VPSHUFB ymm1, ymm2, ymm3/m256
Run Code Online (Sandbox Code Playgroud)

如何使用AVX内在函数有效地模拟该指令?

同样在这种特殊情况下,源只有8个元素(字节),但这些元素可以在目的地的整个32字节内移动.所以只运行2 x就没问题了PSHUFB.

我发现的一个问题VPSHUFB是它将16(0x10)视为0,只有128和up填充为零!(最高位设置)是否可以在不添加比较和屏蔽的情况下执行此操作?

x86 simd intrinsics avx

6
推荐指数
1
解决办法
1485
查看次数

嵌套循环遍历数组

有2个非常大的系列元素,第二个比第一个大100倍.对于第一个系列的每个元素,第二个系列中有0个或更多元素.这可以通过2个嵌套循环遍历和处理.但是第一个阵列的每个成员的匹配元素数量的不可预测性使得事情变得非常非常缓慢.

第二系列元素的实际处理涉及逻辑和(&)以及人口计数.

我找不到使用C的好的优化,但是我正在考虑使用内联asm,对第一个系列的每个元素执行rep*mov*或类似操作,然后对第二个系列的匹配字节进行批处理,可能在缓冲区中1MB或者其他东西.但是代码会变得非常混乱.

有人知道更好的方法吗?C首选,但x86 ASM也行.非常感谢!

简化问题的示例/演示代码,第一个系列是"人",第二个系列是"事件",为了清楚起见.(最初的问题实际上是100米和10,000米的条目!)

#include <stdio.h>
#include <stdint.h>

#define PEOPLE 1000000    //   1m
struct Person {
    uint8_t age;   // Filtering condition
    uint8_t cnt;   // Number of events for this person in E
} P[PEOPLE]; // Each has 0 or more bytes with bit flags

#define EVENTS 100000000  // 100m
uint8_t P1[EVENTS]; // Property 1 flags
uint8_t P2[EVENTS]; // Property 2 flags

void init_arrays() {
    for (int i = 0; i < PEOPLE; i++) { // just some stuff …
Run Code Online (Sandbox Code Playgroud)

c optimization performance assembly

5
推荐指数
1
解决办法
318
查看次数

字符串外部索引的高效存储

假设您在磁盘上有一个包含 n 个对象的大型集合,每个对象都有一个可变大小的字符串。使用纯字符串比较为这些对象建立索引的有效方法的常见做法是什么。由于大小和 I/O 的原因,将整个字符串存储在索引上从长远来看是令人望而却步的,但由于磁盘具有高延迟,仅存储引用也不是一个好主意。

我一直在考虑使用类似 B 树的设计并尝试使用这种方法,但找不到任何数据库实现。事实上,很难找到主要数据库如何实现字符串索引(它可能会迷失在 SQL 级信息的大量结果中。)

蒂亚!

编辑:将标题从“有效外部排序和搜索具有大字符串的存储对象”更改为“有效存储字符串的外部索引”。

algorithm database-design external-sorting

3
推荐指数
1
解决办法
756
查看次数

检测提交表单的HTTP 204状态

有没有办法获得JavaScript事件或检查提交的表单是否作为响应状态HTTP 204?

javascript forms http

2
推荐指数
1
解决办法
1242
查看次数

优化元素2 ^ x-1的乘法

是否有任何已知的优化,用于乘以已知为2 ^ x-1(1,3,7 ......)的几个(3到5)字节(int8)

这是在使用(2 ^ x-1)/ 2 ^ x多次乘以字节数组的上下文中.除法是微不足道的(为右移添加指数),但分子有点麻烦.

此外,指数x仅在1..31中,并且所有的总和始终小于32.

// In reality there are 16 of these (i.e. a[16], b[16], c[16])
// ( a + b + c ) < 32
char  a = 2;
char  b = 16;
char  c = 8;

// Ratio/scale, there are 16 of these (i.e. r[16])
// It might work storing in log2 and using int8 or int16
// with fixed point approximation
<x?>  r = ( a - 1 ) * …
Run Code Online (Sandbox Code Playgroud)

c simd avx

2
推荐指数
1
解决办法
271
查看次数