【发布时间】:2018-08-20 07:42:03
【问题描述】:
假设我们有一个给定的字符串
DataString DB 'AGIJKSZ', 0FFH ;
在其中找到J 最省时的程序是什么?
时效性是指最少的时钟滴答声。
这是一个带有这些指令集的 x86 处理器:
MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, EM64T, VT-x, AES, AVX, AVX2, FMA3, TSX
假设字符串和搜索的字符都可以更改,但只能通过编辑代码来更改,并且我们总是在寻找单个字符。字符串是 ASCII。字符串结束标记为FF
答案应该只是将EAX 设置为找到1/未找到0。
这是我能想到的
FindChar_1 PROC
MOV ESI, OFFSET DataString ;
SI
MOV AH, 'J' ;
Check_End:
CMP BYTE PTR [ESI], 0FFH ;
JE Not_Find ;
CMP AH, [ESI] ;
'DataString'
JE Got_Equal ;
ADD ESI, 1 ;
JMP Check_End ;
Got_Equal:
MOV DL, [ESI] ;
JMP Done
Not_Find:
MOV EAX,0 ;
RET ;
Done:
MOV EAX,1 ;
RET ;
FindChar_1 ENDP
编辑:
现在我意识到我应该提到其他一些事情。我使用的是 masm32,所以我可以使用的指令仅限于非常基本的指令。
【问题讨论】:
-
在什么 CPU 上? x86 与 SSE2? AVX2?什么微架构?搜索模式是固定常数吗?还是字符串是固定常量(就像您在此处显示的那样)而要查找的字符是可变的?或者都是运行时变量?字符串长度是可变的吗?如果它很长,它是否在缓存中很热? 搜索模式是否总是一个字节? 优化
strchr与strstr的功能非常不同。字符串是 ASCII,还是像 UTF-8 这样的可变宽度编码? -
tl;dr 这远 太宽泛了,甚至不清楚你在问什么问题。我的意思是在这种情况下最有效的是
Jpos equ 4,如果模式和字符串都是常量,那么结果就是常量。 (这是速度不依赖于 CPU 的一种情况:P) -
好的,所以是带有 AVX2 的 CPU。 Ryzen、挖掘机、Haswell、Broadwell、Skylake 还是 Knight's Landing?不同的微架构会为不同的操作占用不同数量的时钟周期,并且具有不同的能力来乱序执行周围代码的搜索。 (agner.org/optimize 和 stackoverflow.com/tags/x86/info)。周围的代码是否对字符串搜索的延迟或总 uop 吞吐量有瓶颈?即您是否针对延迟或吞吐量进行了优化?总时钟周期不是代码每个部分的时钟总和。
-
字符串的长度是如何确定的?它是 NULL 终止的吗?它有固定的长度吗?我们是否可以读取字符串的末尾?是否提前知道角色会出现?
-
您说字符串和搜索模式都可以是构建时常量,但这使问题变得愚蠢:将答案硬编码为
JPos equ 4。那么我们可以做出哪些假设呢?字符串对齐到 16 字节还是 32 字节?或者至少,我们可以假设加载向量不会出现段错误吗?你需要什么形式的结果?整数寄存器中的指针?矢量中的位图?一个真/假条件而不需要知道它在哪里?按条件分支?
标签: search assembly optimization string-search