性无码一区二区三区在线观看,少妇被爽到高潮在线观看,午夜精品一区二区三区,无码中文字幕人妻在线一区二区三区,无码精品国产一区二区三区免费

徐土豆
認(rèn)證:優(yōu)質(zhì)創(chuàng)作者
所在專(zhuān)題目錄 查看專(zhuān)題
C語(yǔ)言中去除不必要的內(nèi)存引用可以有效地提高性能
C語(yǔ)言中內(nèi)循環(huán)和外循環(huán)的位置可能產(chǎn)生性能上的區(qū)別
[C語(yǔ)言朝花夕拾] C語(yǔ)言中的命令行輸入?yún)?shù)判斷
用“位操作”取代“取模操作”判斷奇數(shù)偶數(shù)
c語(yǔ)言運(yùn)行時(shí)出現(xiàn)segment fault的原因
一文理解C語(yǔ)言中的volatile修飾符
作者動(dòng)態(tài) 更多
大模型推理時(shí)的尺度擴(kuò)展定律
13小時(shí)前
世界多胞體與世界模型
6天前
獎(jiǎng)勵(lì)模型中的尺度擴(kuò)展定律和獎(jiǎng)勵(lì)劫持
1星期前
MeCo——給預(yù)訓(xùn)練數(shù)據(jù)增加源信息,就能減少33%的訓(xùn)練量并且提升效果
2星期前
DoReMi——一種通過(guò)代理模型估計(jì)大模型預(yù)訓(xùn)練最佳數(shù)據(jù)配比的方法
2星期前

C語(yǔ)言中去除不必要的內(nèi)存引用可以有效地提高性能

版權(quán)聲明:本文為博主原創(chuàng)文章,遵循 CC 4.0 BY-SA 版權(quán)協(xié)議,轉(zhuǎn)載請(qǐng)附上原文出處鏈接和本聲明。
在C語(yǔ)言中,我們經(jīng)常會(huì)存在對(duì)某個(gè)內(nèi)存地址進(jìn)行引用的操作,也就是如下列代碼所示的,對(duì)指針進(jìn)行取內(nèi)容:
int vars[10];
int var = *(vars+3); //這里就是對(duì)數(shù)組vars的第三個(gè)元素進(jìn)行引用
這種內(nèi)存引用操作對(duì)應(yīng)的匯編代碼通常如:
mov (%rax), %rdx; 
# 把地址位于%rax的內(nèi)存值進(jìn)行取出。
mov 12(%rax), %rdx;
# 把地址位于%rax+12的內(nèi)存值進(jìn)行取出。
我們注意到這種操作涉及到了CPU從數(shù)據(jù)總線中向內(nèi)存中取值,通常速度遠(yuǎn)遠(yuǎn)慢于CPU本身的計(jì)算操作,也慢于CPU取出內(nèi)部寄存器值的操作,很多時(shí)候,一個(gè)程序的計(jì)算瓶頸就在這些去內(nèi)存的操作中,因此要盡量避免不必要的內(nèi)存引用。以下舉個(gè)代碼例子進(jìn)行進(jìn)一步說(shuō)明。
// code_1.c
#include <stdio.h>
void foo(float vars[], int length, float *sum){
	int i = 0;
	for (i = 0; i < length; i++){
		*sum = *sum * vars[i];
	}
}

int main(){
	float sum = 1;
	float vars[] = {0.3,0.4,0.13,0.65,0.23,0.87,0.2,1.34};
	int cycle = 0;
	for (cycle = 0; cycle < 100000000; cycle++){
		foo(vars, 8, &sum);
		sum = 1;
	}
	return 0;
}
// code_2.c
#include <stdio.h>
void foo(float vars[], int length, float *sum){
	int i = 0;
	int tmp = *sum;
	for (i = 0; i < length; i++){
		tmp = tmp * vars[i];
	}
	*sum = tmp;
}

int main(){
	float sum = 1;
	float vars[] = {0.3,0.4,0.13,0.65,0.23,0.87,0.2,1.34};
	int cycle = 0;
	for (cycle = 0; cycle < 100000000; cycle++){
		foo(vars, 8, &sum);
		sum = 1;
	}
	return 0;
}
code_1.ccode_2.c的差別很小,就是在于函數(shù)foo()中關(guān)于sum這個(gè)指針的指向的內(nèi)容的更新方式,第一種方式是每一個(gè)循環(huán)中都進(jìn)行更新,顯然其需要更多但是卻沒(méi)必要的內(nèi)存引用,第二種通過(guò)一個(gè)臨時(shí)變量的形式,避免了多次頻繁無(wú)用地訪問(wèn)內(nèi)存。觀察其兩者的匯編,就會(huì)發(fā)現(xiàn)和我們之前分析的是一致的。我們采用-O1優(yōu)化選項(xiàng),命令如:
gcc -O1 -S code_1.c
gcc -O1 -S code_2.c
匯編結(jié)果如下所示(以下匯編只是截取部分關(guān)鍵信息)
# code_1.s
.L3:
	movss (%rdx), %xmm0
	mulss (%rax), %xmm0
	movss %xmm0, (%rdx)
	addq %4, %rax
	cmpq %rcx, %rax
	jne .L3
而第二個(gè)則簡(jiǎn)單很多
# code_1.s
.L3:
	mulss (%rax), %xmm0
	addq %4, %rax
	cmpq %rcx, %rax
	jne .L3
我們發(fā)現(xiàn),第一個(gè)代碼比起第二個(gè)代碼多出很多內(nèi)存引用操作,其需要從內(nèi)存中取出乘數(shù) movss (%rdx), %xmm0,計(jì)算完之后,有需要更新,將其寫(xiě)回內(nèi)存, movss %xmm0, (%rdx)。導(dǎo)致其性能遜于后者。在筆者的服務(wù)器上,兩者的性能具體對(duì)比為:code 1跑了0.54s,而code 2跑了0.37s。

同時(shí)我們發(fā)現(xiàn),編譯器很難對(duì)此進(jìn)行優(yōu)化,在-O1優(yōu)化等級(jí)下,其表現(xiàn)和我們分析的并沒(méi)有區(qū)別(某些編譯器優(yōu)化會(huì)導(dǎo)致代碼分析和實(shí)際的匯編有所區(qū)別),其還沒(méi)有能夠智能到對(duì)這種進(jìn)行優(yōu)化,因此需要程序員對(duì)此進(jìn)行顯式地優(yōu)化。
聲明:本內(nèi)容為作者獨(dú)立觀點(diǎn),不代表電子星球立場(chǎng)。未經(jīng)允許不得轉(zhuǎn)載。授權(quán)事宜與稿件投訴,請(qǐng)聯(lián)系:editor@netbroad.com
覺(jué)得內(nèi)容不錯(cuò)的朋友,別忘了一鍵三連哦!
贊 2
收藏 3
關(guān)注 52
成為作者 賺取收益
全部留言
0/200
成為第一個(gè)和作者交流的人吧