由买买提看人间百态

boards

本页内容为未名空间相应帖子的节选和存档,一周内的贴子最多显示50字,超过一周显示500字 访问原贴
Programming版 - 两个古董的C优化代码,现在还有效果么?
相关主题
请教:属于google不到答案的问题[合集] 3-4G内存的机器,到底跑64位还是32位OS快?
CIH源代码C++ software engineer 3 years expectation
round function in math以下两个C 代码是不是完全等价?
今天被一个面试问题难住了C编译器为何允许一个函数在某个路径不返回值?
线程中可以循环延时吗?int 和 unsigned int 比大小会出问题 c++
C++在linux下读一次系统时间要多少时间C 多线程的一个问题
C++的牛B之处你们都还没体会到alloc这个函数究竟做些啥活呢?
请不要盲目崇拜FP语言关于Dword 和 word
相关话题的讨论汇总
话题: rdtsc话题: avg1话题: avg2话题: std话题: 1000000
进入Programming版参与讨论
1 (共1页)
k****f
发帖数: 3794
1
1。for loop,测试0比测试n要快。
for(i=n-1;i>=0;i--) 替代 for(i=0;i 2。节省转跳分支
i+= !(!(j)); 替代 if( j!=0 ) i++;
现在的编译还需要这种古怪的写法么?
y*******g
发帖数: 6599
2
有必要吗?
如果这段不是瓶颈的话

【在 k****f 的大作中提到】
: 1。for loop,测试0比测试n要快。
: for(i=n-1;i>=0;i--) 替代 for(i=0;i: 2。节省转跳分支
: i+= !(!(j)); 替代 if( j!=0 ) i++;
: 现在的编译还需要这种古怪的写法么?

x******c
发帖数: 13
3
these really depends on the CPU it runs on...
anyway, for 1, it probably makes no difference
for 2, I think it makes a difference on performance critical code. branch
mis-predication usually has a pretty high cost
k****f
发帖数: 3794
4
对应常见的intel/amd cpu呢?有没有什么定论呢?

【在 x******c 的大作中提到】
: these really depends on the CPU it runs on...
: anyway, for 1, it probably makes no difference
: for 2, I think it makes a difference on performance critical code. branch
: mis-predication usually has a pretty high cost

x******c
发帖数: 13
5
what I said above is for modern intel/amd cpus.
No one can say for sure without profiling/benchmarking though.
As a general rule: don't write code like that.
If your code is not fast enough, use a profiler to identify the most
performance critical parts, then try these to see if it helps.
r*********r
发帖数: 3195
6
第二个可能有用。因为跳转会清空流水线,现在的cpu都有几十级流水线,
清一次就慢很多。
B********e
发帖数: 1062
7
1 is used pretty often.
The accumulation for all the loops may have huge effects.

【在 k****f 的大作中提到】
: 1。for loop,测试0比测试n要快。
: for(i=n-1;i>=0;i--) 替代 for(i=0;i: 2。节省转跳分支
: i+= !(!(j)); 替代 if( j!=0 ) i++;
: 现在的编译还需要这种古怪的写法么?

b***i
发帖数: 3043
8
2是怎么实现的?写成汇编语言试试

【在 k****f 的大作中提到】
: 1。for loop,测试0比测试n要快。
: for(i=n-1;i>=0;i--) 替代 for(i=0;i: 2。节省转跳分支
: i+= !(!(j)); 替代 if( j!=0 ) i++;
: 现在的编译还需要这种古怪的写法么?

c**d
发帖数: 580
9
给2写一下汇编,肯定有不对的地方,太久远。。。
x86 assember:
mov EBX [addr of i]
mov ECX [addr of j]
neg ECX
neg ECX
add EBX ECX
c**d
发帖数: 580
10
第一个因为有JZ,去检查EFLAGS,所以i-- 更快些。
不过现在的compiler应该对付这个不是问题,而且还有循环展开什么的。区别应该很小
了。
相关主题
C++在linux下读一次系统时间要多少时间[合集] 3-4G内存的机器,到底跑64位还是32位OS快?
C++的牛B之处你们都还没体会到C++ software engineer 3 years expectation
请不要盲目崇拜FP语言以下两个C 代码是不是完全等价?
进入Programming版参与讨论
t****t
发帖数: 6806
11
你这个太不对了, 差十万八千里
neg对应C的操作符是~,不是!
剩下的自己想吧

【在 c**d 的大作中提到】
: 给2写一下汇编,肯定有不对的地方,太久远。。。
: x86 assember:
: mov EBX [addr of i]
: mov ECX [addr of j]
: neg ECX
: neg ECX
: add EBX ECX

c**d
发帖数: 580
12
好像必须要CMP,看了一眼手册。
有人写不用CMP的么?
t****t
发帖数: 6806
13
CMP不是关键问题, 关键是不要分支
一般在x86上用setcc来去掉分支
比如说
mov ebx, a
xor eax, eax
test ebx, ebx /* 一般测试0用这个 */
setnz al
/* eax=(a!=0) */

【在 c**d 的大作中提到】
: 好像必须要CMP,看了一眼手册。
: 有人写不用CMP的么?

T*****9
发帖数: 2484
14
问一个
我到现在还不是很了解x86怎么用xchg实现test_and_set的。。。

【在 t****t 的大作中提到】
: CMP不是关键问题, 关键是不要分支
: 一般在x86上用setcc来去掉分支
: 比如说
: mov ebx, a
: xor eax, eax
: test ebx, ebx /* 一般测试0用这个 */
: setnz al
: /* eax=(a!=0) */

D*******a
发帖数: 3688
15
setcc是几86出来的指令?
另,也可以:
lahf
shr ax, 14 //把0-flag移到最低位
and ax, 1

【在 t****t 的大作中提到】
: CMP不是关键问题, 关键是不要分支
: 一般在x86上用setcc来去掉分支
: 比如说
: mov ebx, a
: xor eax, eax
: test ebx, ebx /* 一般测试0用这个 */
: setnz al
: /* eax=(a!=0) */

c**d
发帖数: 580
16
setnz 是386以后的,估计real和protected模式都不干活说。
t****t
发帖数: 6806
17
setcc的确是386以上才有的.
不过现在还有386以下的机器吗, 现在的OS还有哪个能在286以下跑的?
什么叫real和protected模式都不干活? 你多半模式之间的区别都没搞明白.

【在 c**d 的大作中提到】
: setnz 是386以后的,估计real和protected模式都不干活说。
t****t
发帖数: 6806
18
没什么啊, 就是xchg自动lock, 所以它总是atomic的
比如说一直换一个0到lock
如果换出来一个1就拿到了lock, 如果换出来的还是0就是没拿到接着等

【在 T*****9 的大作中提到】
: 问一个
: 我到现在还不是很了解x86怎么用xchg实现test_and_set的。。。

g****g
发帖数: 310
19
绝对没必要,也不应该写这类代码。根本没有任何速度上的提升。(如果有,那么是在
你做梦的时候)
unsigned long avg1=0, avg2=0;
for (int n=0;n<1000000; n++)
{
int j = 0, i=0;
a = rdtsc();
i+= !(!(j));
b=rdtsc()-a;
avg1+=b;
j=0; i=1;
a = rdtsc();
if( j!=0 ) i++;
b=rdtsc()-a;
avg2+=b;
j++;i++;

}
std::cout << "Take:" << avg1/1000000 << std::endl;
std::cout << "Take:" << avg2/1000000 << std::endl;
两者的结果基本相同。
k****f
发帖数: 3794
20
你这个代码会被编译器优化掉的,j=0就被直接拿去优化i+=!(!j)
你应该产生n个随机数放到数组里面,是0和非0个数差不多的,这样子才能比较好。

【在 g****g 的大作中提到】
: 绝对没必要,也不应该写这类代码。根本没有任何速度上的提升。(如果有,那么是在
: 你做梦的时候)
: unsigned long avg1=0, avg2=0;
: for (int n=0;n<1000000; n++)
: {
: int j = 0, i=0;
: a = rdtsc();
: i+= !(!(j));
: b=rdtsc()-a;
: avg1+=b;

相关主题
C编译器为何允许一个函数在某个路径不返回值?alloc这个函数究竟做些啥活呢?
int 和 unsigned int 比大小会出问题 c++关于Dword 和 word
C 多线程的一个问题汇编的mov指令
进入Programming版参与讨论
g****g
发帖数: 310
21
楼上的你没看到每次循环后j++么?
g****g
发帖数: 310
22
一样的结果,整天讨论哪个快,却自己不去测试一下有意义么?
unsigned long avg1=0, avg2=0;
srand( (unsigned)time( NULL ) );
int j = 0, i=0;
for (int n=0;n<1000000; n++)
{
j = (rand() > RAND_MAX/2) ? 0 : 1;
a = rdtsc();
i+= !(!(j));
b=rdtsc()-a;
avg1+=b;
j=0; i=1;
a = rdtsc();
if( j!=0 ) i++;
b=rdtsc()-a;
avg2+=b;

}
std::cout << "Take:" << avg1/1000000 << std::endl;
std::cout << "Take:" << avg2/1000000 << std:

【在 k****f 的大作中提到】
: 你这个代码会被编译器优化掉的,j=0就被直接拿去优化i+=!(!j)
: 你应该产生n个随机数放到数组里面,是0和非0个数差不多的,这样子才能比较好。

k****f
发帖数: 3794
23
你把j放到循环体了
j++有个鸟用

【在 g****g 的大作中提到】
: 楼上的你没看到每次循环后j++么?
g****g
发帖数: 310
24
对于1,可以肯定告诉你,不存在任何速度上的差别。

【在 k****f 的大作中提到】
: 1。for loop,测试0比测试n要快。
: for(i=n-1;i>=0;i--) 替代 for(i=0;i: 2。节省转跳分支
: i+= !(!(j)); 替代 if( j!=0 ) i++;
: 现在的编译还需要这种古怪的写法么?

g****g
发帖数: 310
25
rand也测过了,根本没区别,你干吗不自己去试试?

【在 k****f 的大作中提到】
: 你把j放到循环体了
: j++有个鸟用

g****g
发帖数: 310
26
wrong, no difference at all, can you test before post?

【在 B********e 的大作中提到】
: 1 is used pretty often.
: The accumulation for all the loops may have huge effects.

t****t
发帖数: 6806
27
2其实我知道是没什么区别的, 现在的编译器去分支还可以
不过你贴的例子确实是不对啊.

【在 g****g 的大作中提到】
: rand也测过了,根本没区别,你干吗不自己去试试?
k****f
发帖数: 3794
28
嗯,我看过GCC的汇编结果了
不加优化,确实是有jmp指令的
一加了优化选项,比如O3,jmp就没有了,被setne之类替换掉的
结果两个c代码编译出来就一样了

【在 t****t 的大作中提到】
: 2其实我知道是没什么区别的, 现在的编译器去分支还可以
: 不过你贴的例子确实是不对啊.

g****g
发帖数: 310
29
我的结论:
对于那个for循环,两者完全一样,
对于i+= !(!(j)); 替代 if( j!=0 ) i++;
i+= !(!(j))快,如果这段代码很critical,那么你可以这么改。
g****g
发帖数: 310
30
不加任何优化的代码
if( j!=0 ) i++;
0041DD87 837D B0 00 CMP DWORD PTR SS:[EBP-50],0
0041DD8B 74 09 JE SHORT test2.0041DD96
0041DD8D 8B45 A4 MOV EAX,DWORD PTR SS:[EBP-5C]
0041DD90 83C0 01 ADD EAX,1
0041DD93 8945 A4 MOV DWORD PTR SS:[EBP-5C],EAX
i+= !(!(j));
0041DD0D 33C0 XOR EAX,EAX
0041DD0F 837D B0 00 CMP DWORD PTR SS:[EBP-50],0
0041DD13 0F95C0 SETNE AL
0041DD16 0345 A4 ADD EAX,DWORD PTR SS:[EBP-5C]
0041DD19
相关主题
VC++里一个函数有参数[out]LPWSTR p要不要初始化?CIH源代码
请教一个c语言实现多线程的问题round function in math
请教:属于google不到答案的问题今天被一个面试问题难住了
进入Programming版参与讨论
g****g
发帖数: 310
31
我的结论:
对于那个for循环,两者完全一样,
对于i+= !(!(j)); 替代 if( j!=0 ) i++;
i+= !(!(j))快,如果这段代码很critical,那么你可以这么改。
t****t
发帖数: 6806
32
不加优化比较根本没意义

【在 g****g 的大作中提到】
: 不加任何优化的代码
: if( j!=0 ) i++;
: 0041DD87 837D B0 00 CMP DWORD PTR SS:[EBP-50],0
: 0041DD8B 74 09 JE SHORT test2.0041DD96
: 0041DD8D 8B45 A4 MOV EAX,DWORD PTR SS:[EBP-5C]
: 0041DD90 83C0 01 ADD EAX,1
: 0041DD93 8945 A4 MOV DWORD PTR SS:[EBP-5C],EAX
: i+= !(!(j));
: 0041DD0D 33C0 XOR EAX,EAX
: 0041DD0F 837D B0 00 CMP DWORD PTR SS:[EBP-50],0

T*****9
发帖数: 2484
33
xchg会自动lock?
我一直以为就是交换寄存器和mem的值

【在 t****t 的大作中提到】
: 没什么啊, 就是xchg自动lock, 所以它总是atomic的
: 比如说一直换一个0到lock
: 如果换出来一个1就拿到了lock, 如果换出来的还是0就是没拿到接着等

N********n
发帖数: 8363
34
Don't write code that makes your co-worker cringe.

【在 k****f 的大作中提到】
: 1。for loop,测试0比测试n要快。
: for(i=n-1;i>=0;i--) 替代 for(i=0;i: 2。节省转跳分支
: i+= !(!(j)); 替代 if( j!=0 ) i++;
: 现在的编译还需要这种古怪的写法么?

1 (共1页)
进入Programming版参与讨论
相关主题
关于Dword 和 word线程中可以循环延时吗?
汇编的mov指令C++在linux下读一次系统时间要多少时间
VC++里一个函数有参数[out]LPWSTR p要不要初始化?C++的牛B之处你们都还没体会到
请教一个c语言实现多线程的问题请不要盲目崇拜FP语言
请教:属于google不到答案的问题[合集] 3-4G内存的机器,到底跑64位还是32位OS快?
CIH源代码C++ software engineer 3 years expectation
round function in math以下两个C 代码是不是完全等价?
今天被一个面试问题难住了C编译器为何允许一个函数在某个路径不返回值?
相关话题的讨论汇总
话题: rdtsc话题: avg1话题: avg2话题: std话题: 1000000