又求解释:

iamnobody 2011-10-13 03:04:22
还是做了一个strlen()函数的测试:
my::strlen() PK std::strlen();
问题1:

我用内联汇编用scas指令写的函数用时竟然稳定地保持在std::strlen()“优化”板本的三倍,他的“优化”后的核心代码是:


01181040 mov cl,byte ptr [eax]
01181042 inc eax
01181043 test cl,cl
01181045 jne main+40h (1181040h)


然后我用内联汇编写:



size_t strlen(char* pch){

char* pcrr;
_asm{
mov edi,pch
xor ecx,ecx
cld
dec ecx
xor eax,eax
repne scasb
mov pcrr,edi

}
return pcrr - pch;
}

优化后也差不多这个样。
为什么 scasb指针会这么慢,竟然比不上普通的mov 和 jne

问题2:std::strlen()的代码也有看过,在不release时比release时快,这个之前讨论过了。下面是根据类似原理写的strlen(),想不到在我的编译器上还是被优化成了这个鸟样:


size_t strlen(char* pch){

char * pcrr = pch - 1;
int x;
do{
pcrr++;
if (((int)pcrr) & 3 == 0){
do{
pcrr += 4;
x = *(int*)pcrr;
}while(!((x - 0x01010101) & ~x & 0x80808080));
pcrr -= 4;
}
}while(*pcrr != '\0');
return pcrr - pch;
}


release后:

00121057 inc esi
00121058 cmp byte ptr [esi],0
0012105B jne main+57h (121057h)


问题2:怎么控制编译器的这种低效的优化?我记得以前它还会按照我写法四个字节比较的。以前优化后是这样的:

012610D0 mov eax,dword ptr [ebx]
012610D2 lea edx,[eax-1010101h]
012610D8 not eax
012610DA and edx,eax
012610DC add ebx,4
012610DF test edx,80808080h
012610E5 je main+90h (12610D0h)



主函数代码:

const int num = 1024 * 1024 * 32;
static char arr[num];
memset(arr,'1',num);
0118100C push 2000000h
01181011 push 31h
01181013 push offset arr (1183370h)
01181018 call memset (1181BFAh)
arr[num - 1] = 0;
clock_t beg = clock();
0118101D mov ebx,dword ptr [__imp__clock (11820D4h)]
01181023 add esp,0Ch
01181026 mov byte ptr ds:[318336Fh],0
0118102D call ebx
0118102F mov dword ptr [esp+14h],eax
int len1 = strlen(arr);
01181033 mov eax,offset arr (1183370h)
01181038 lea edx,[eax+1]
0118103B jmp main+40h (1181040h)
0118103D lea ecx,[ecx]
01181040 mov cl,byte ptr [eax]
01181042 inc eax
01181043 test cl,cl
01181045 jne main+40h (1181040h)
01181047 sub eax,edx
01181049 mov dword ptr [esp+10h],eax
clock_t mid = clock();
0118104D call ebx
0118104F mov esi,eax
int len2 = my::strlen(arr);
01181051 mov edi,offset arr (1183370h)
01181056 xor ecx,ecx
01181058 cld
01181059 dec ecx
0118105A xor eax,eax
0118105C repne scas byte ptr es:[edi]
0118105E mov dword ptr [esp+0Ch],edi
clock_t end = clock();
01181062 call ebx

...全文
264 8 打赏 收藏 转发到动态 举报
写回复
用AI写文章
8 条回复
切换为时间正序
请发表友善的回复…
发表回复
iamnobody 2011-10-13
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 keiy 的回复:]
问题1:可查intel每条指令的clocks,自己算一下.不过我暂时只找到scasb为12个时钟周期,还要考虑不同CPU的相同指令时钟周期不同,加上流水线优化等,但我感觉这个是可能的.
问题2:编译器都有控制优化指令-O,你试一下你不同-O参数的结果,当然也可能达不到你的要求,那就是编译器的问题了.所以编译器所带的库文件,很多也是ASM写的而非C/C++,以前研究过borland的字串strcp……
[/Quote]

rep scasb 9 + 4*cx
7 if cx=0
查到了,是pentium的。没什么不妥。。。
同样的次数竟然比普通循环慢那么多。。。
lengxujun 2011-10-13
  • 打赏
  • 举报
回复
对于编译器来说,在做优化的时候,对于达到同样功能的代码段,如果它越难“理解”你的代码逻辑,所能做出的优化效果越差。也就是说,你用编写的表面上更高效的代码,可能比不上表面更糟糕但更容易被编译器“理解”的代码。这也就是你在debug模式下的代码(表面上更高效但不那么被编译器“理解”,代码未经过优化),而release模式下优化时缺翻译成了更低效的代码(因为编译器没“理解”的真正意图)。
这些涉及到编译器的优化理论,lz可以专门研究一下(管窥优化等等之类的)。

一家之言,仅供参考。
柯本 2011-10-13
  • 打赏
  • 举报
回复
问题1:可查intel每条指令的clocks,自己算一下.不过我暂时只找到scasb为12个时钟周期,还要考虑不同CPU的相同指令时钟周期不同,加上流水线优化等,但我感觉这个是可能的.
问题2:编译器都有控制优化指令-O,你试一下你不同-O参数的结果,当然也可能达不到你的要求,那就是编译器的问题了.所以编译器所带的库文件,很多也是ASM写的而非C/C++,以前研究过borland的字串strcpy就是用asm写的,它是用每次拷贝一字长(4字节)以提高速度

;[]-----------------------------------------------------------------[]
;| QSTRCPY.ASM -- copy string src to string dest (quick version) |
;[]-----------------------------------------------------------------[]

DWALIGN equ 1 ; set to 1 to enable dword-aligning of string

;
; C/C++ Run Time Library - Version 11.0
;
; Copyright (c) 1991, 2002 by Borland Software Corporation
; All Rights Reserved.
;

; $Revision: 9.4.2.1 $

include RULES.ASI

; Segments Definitions

Header@

;-----------------------------------------------------------------------
;
;Name __strcpy__ - copy string src to string dest
;
;Usage char *__strcpy__ (char *dest, const char *src);
;
;Prototype in string.h
;
;Description Copy the ASCIIZ string *src to the buffer *dest. It is the
; callers responsibility to ensure that the dest buffer is
; large enough to contain the string, and to guard against
; supplying NULL arguments.
;
; NOTE: this is the "quick" version of strcpy; it cheats
; by fetching 32-bit words, which can GP fault if the
; src string is near the end of a memory region and DWALIGN
; is not enabled above.
;
;Return value __strcpy__ returns dest.
;
;-----------------------------------------------------------------------

Code_seg@

Func@ __strcpy__, public, _RTLENTRYF, <pointer dest>, <pointer src>

Link@
mov ecx, src ; get source string
mov edx, dest ; get destination buffer
if DWALIGN
mov eax, ecx
and eax, 3
jmp jmptab[eax*4]

jmptab dd offset FLAT:fetch
dd offset FLAT:fetch3
dd offset FLAT:fetch2
dd offset FLAT:fetch1

; Copy three bytes

fetch3:
mov al, [ecx]
or al, al
je return0
mov [edx], al
add ecx, 1
add edx, 1

; Copy two bytes

fetch2:
mov al, [ecx]
or al, al
je return0
mov [edx], al
add ecx, 1
add edx, 1

; Copy one byte

fetch1:
mov al, [ecx]
or al, al
je return0
mov [edx], al
add ecx, 1
add edx, 1

; jmp fetch

endif ; DWALIGN

fetch:
mov eax, [ecx] ; get four bytes from source
or al, al ; check byte 0 for null
jz return0
or ah, ah ; check byte 1 for null
jz return1
test eax, 000ff0000h ; check byte 2 for null
jz return2
test eax, 0ff000000h ; check byte 3 for null
jz return3
mov [edx], eax
add ecx, 4
add edx, 4
jmp fetch
return3:
mov [edx], eax ; copy bytes 0-3
mov eax, dest ; return dest
Unlink@
Return@
return2:
mov [edx], ax ; copy bytes 0-2
mov byte ptr [edx+2], 0
mov eax, dest ; return dest
Unlink@
Return@
return1:
mov [edx], ax ; copy bytes 0-1
mov eax, dest ; return dest
Unlink@
Return@
return0:
mov [edx], al ; copy byte 0
mov eax, dest ; return dest
Unlink@
Return@

EndFunc@ __strcpy__

Code_EndS@

end

qq120848369 2011-10-13
  • 打赏
  • 举报
回复
表示没学过汇编。
zuo187qiang 2011-10-13
  • 打赏
  • 举报
回复
帮顶...菜鸟看不懂....
PG 2011-10-13
  • 打赏
  • 举报
回复
LZ数据帝啊,膜拜~~帮顶~~~
周晓荣 2011-10-13
  • 打赏
  • 举报
回复
mark~~~

帮顶,等会看。
iamnobody 2011-10-13
  • 打赏
  • 举报
回复
问题2是我2了,忘了加括号:(((int)pcrr) & 3 == 0) =》 ((((int)pcrr) & 3) == 0){

,请高手回答问题1:::
源码链接: https://pan.quark.cn/s/4059260b3dc9 在电子设计自动化(EDA)范畴内,Verilog作为一项关键的硬件描述语言(HDL),被普遍应用于构建数字系统的模型,其应用范围涵盖从基础的逻辑门构造到高级的系统级设计,例如本案例所探讨的电梯系统。运用Verilog进行的电梯系统构建是一个典型的综合实践任务,它融合了数字逻辑、嵌入式系统以及计算机工程等多个核心知识领域。 我们必须明确电梯系统的功能要求。电梯需依据乘客的楼层指令,智能地选择其运行路径、选择停靠的楼层以及安排门的开启流程。这一过程涉及到状态机的设计,这是Verilog编程中的一个核心概念。状态机能够将电梯的操作流程划分为多个独立的状态,例如待机、上行、下行、开门、关门等,通过状态间的转换条件来执行各类操作。 Verilog程序通常由多个模块构成,每个模块对应电路的一部分。在此项目中,可能包含以下模块:主控制单元模块、楼层识别模块、按键输入单元模块、电机驱动模块等。各模块均具备特定的功能,例如主控制单元负责统筹各部分的工作,而电机驱动模块则依据指令操控电梯的升降动作。 在构建电梯系统时,还需关注实时性和同步性。例如,电梯不允许在两个楼层同时开启门,这需要在Verilog程序中运用适当的同步手段,例如边沿触发的时钟信号,以确保数据传输的精确性与统一性。 接下来是仿真环节和验证步骤。借助ModelSim或Vivado这类软件工具,我们可以对Verilog程序进行仿真,模拟电梯的操作情形,考察其在不同情境下的表现是否符合设计预期。此步骤极为关键,有助于识别并修正设计中的缺陷。 倘若设计满足所有条件,可将Verilog程序编译并上传至FPGA(现场可编程门阵列)进行硬件层...
内容概要:本文基于Simulink平台,构建了一个包含风能、太阳能、储能系统和质子交换膜(PEM)电解水制氢系统并网运行的交流母线协调仿真模型。该模型旨在研究多种能源形式与制氢负荷在共用交流母线下的协调运行机制,重点分析风光出力波动性对系统稳定性的影响,以及储能与制氢负荷在能量调节和消纳富余可再生能源方面的作用。通过设计合理的控制策略,实现系统内功率的动态平衡与高效利用,并对系统在不同工况下的动态响应特性进行了仿真验证,为高比例可再生能源接入背景下风光储氢一体化系统的规划与运行提供了技术参考。; 适合人群:具备一定电力系统、新能源或自动化专业背景,从事相关领域研究或工程应用的研发人员及高年级本科生、研究生。; 使用场景及目标:①研究风光储氢多能互补系统的集成与协调控制策略;②分析储能与电解制氢负荷在平抑可再生能源波动、提升系统稳定性方面的作用;③掌握基于Simulink的多能源系统建模仿真方法,服务于科研项目、毕业设计或工程预研。; 阅读建议:建议结合Simulink软件动手复现模型,重点关注各单元模块的控制逻辑与接口设计,通过调整参数和工况进行对比仿真,深入理解系统动态特性与协调运行机理。
下载代码方式:https://pan.quark.cn/s/06ddd041bd02 STM32CubeIDE是由STMicroelectronics(意法半导体)开发的一款功能全面的集成开发平台,主要面向STM32微控制器的应用。该v1.0.2版本特别适配于Windows操作系统,并且能够适用于x86及x64架构的计算机系统。STM32CubeIDE融合了代码编写、编译执行、调试诊断以及项目管理等多项核心功能,致力于精简STM32应用的开发步骤,从而显著提升开发工作的效率。 STM32CubeIDE的主要特性具体包含: 1. **集成开发环境(IDE)**:该平台提供了一个统一的操作界面,开发者能够在此平台上进行代码的编写、编译、链接以及调试STM32应用程序。IDE的设计注重用户体验,支持包括C和C++在内的多种编程语言。 2. **代码生成器**:STM32CubeMX作为STM32CubeIDE的一个组成部分,是一个图形化的配置工具,用户可以通过它来设定微控制器的多种参数,例如时钟系统配置、外设接口选择等。完成配置后,该工具能够自动生成初始化代码,从而大幅减少手动编写基础代码的工作量。 3. **项目模板**:STM32CubeIDE提供了多种预先配置好的项目模板,这些模板覆盖了STM32系列的不同微控制器型号,从而使得新项目的启动过程更加迅速和便捷。 4. **调试工具**:IDE内建了功能强大的调试器,支持JTAG和SWD接口,且兼容多种ST-LINK/V2、ST-LINK/V3以及各类第三方调试设备。调试功能涵盖了断点设置、变量监控、内存检查、性能评估等多个方面。 5. **编译工具链**:STM32CubeIDE集成了GCC编译器以及针对ARM...

65,213

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧