我给自己设定了优化 C 语言中的 strcmp 函数的任务。我通过两种方式完成了这个任务:
strcmp 工作时间为 0.000002 秒 my_strcmp 工作 0.000851 秒 my_strcmp2 工作 0.017444 秒
我非常感谢您关于如何优化 strcmp 函数以实现更快的执行时间的建议。在此上下文中,字符串长度限制为 32 个字符。
编译:nasm -g -f elf64 my_strcmp2.asm -o my_strcmp2.o g++ my_strcmp2.o main.cpp -march=znver3 -O3 -o 应用程序
main.cpp:
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <immintrin.h>
int my_strcmp(const char* word1, const char* word2);
extern "C" int my_strcmp2(const char* word1, const char* word2);
double timer(int (*func)(const char*, const char*));
int main()
{
int j = 0;
const char* word1 = "my name is";
const char* word2 = "my name are";
clock_t begin = clock();
for (int i = 0; i < 1000000; i++)
{
j = strcmp(word1, word2);
}
clock_t end = clock();
fprintf(stderr, "strcmp : %lf seconds\n", (double)(end - begin) / CLOCKS_PER_SEC);
begin = clock();
for (int i = 0; i < 1000000; i++)
{
j = my_strcmp(word1, word2);
}
end = clock();
fprintf(stderr, "my_strcmp : %lf seconds\n", (double)(end - begin) / CLOCKS_PER_SEC);
begin = clock();
for (int i = 0; i < 1000000; i++)
{
j = my_strcmp2(word1, word2);
}
end = clock();
fprintf(stderr, "my_strcmp2 : %lf seconds\n", (double)(end - begin) / CLOCKS_PER_SEC);
return 0;
}
int my_strcmp(const char* word1, const char* word2)
{
__m256i str_reg_1 = _mm256_lddqu_si256((__m256i*)word1);
__m256i str_reg_2 = _mm256_lddqu_si256((__m256i*)word2);
__m256i res_cmp = _mm256_cmpeq_epi8(str_reg_1, str_reg_2);
int mask = ~_mm256_movemask_epi8(res_cmp);
return mask;
}
my_strcmp2.asm:
global my_strcmp2
section .text
my_strcmp2:
cycle:
cmp byte [rel rdi], 0x00
je check_equal
mov dl, byte [rel rsi]
cmp byte [rel rdi], dl
jne not_equal
add rdi, 1
add rsi, 1
jmp cycle
not_equal:
mov rax, 0x01
ret
check_equal:
cmp byte [rel rsi], 0x00
jne not_equal
xor rax, rax
ret
GCC 知道
strcmp
的作用并且可以看到这段代码:
for (int i = 0; i < 1000000; i++)
{
j = strcmp(word1, word2);
}
相当于:
j = strcmp(word1, word2);
因此,它优化了循环,并且每次迭代的时间实际上为零。你不可能用自己的
strcmp
实现来解决这个问题。