Likely and Unlikely

Β· 1208 words Β· 3 minute read

κ°œμš” πŸ”—

μ˜ˆμ „μ— κ΄€λ¦¬ν•˜λ˜ λΈ”λ‘œκ·Έμ—μ„œ μ»€λ„μ—μ„œ μ‚¬μš©ν•˜λŠ” likely와 unlikely 에 λŒ€ν•΄μ„œ μ •λ¦¬ν•œ ν¬μŠ€νŒ…μ΄ μžˆμ—ˆλ‹€. ν•˜μ§€λ§Œ μ‹œκ°„μ΄ μ§€λ‚˜ 컀널 뢄석 책을 λ‹€μ‹œ 보며 likely, unlikelyλ₯Ό λ³΄λ‹ˆ λ‹€μ‹œ ν—·κ°ˆλ¦¬κΈ° μ‹œμž‘ν–ˆλ‹€.

νšŒμ‚¬ μ—…λ¬΄μ—μ„œ μ‹€ν–‰ μ‹œκ°„μ„ μ€„μ΄λŠ” 데에 μ€‘μš”λ„λ₯Ό 두고 μžˆμ§€λ§Œ κ·Έ 방법에 λŒ€ν•΄μ„œλŠ” 아직 닀루지 λͺ»ν•˜κ³  μžˆλ‹€. μ†”λ£¨μ…˜μ΄ μ•ˆμ •ν™”λ˜κ³  전체적인 업무 λ‚΄μš©μ΄ νŒŒμ•…λ˜λ©΄ λ³Έ λ‚΄μš©μ„ μ •λ¦¬ν•˜λ©΄μ„œ μ‹€ν–‰ μ‹œκ°„μ„ κ°μ†Œν•  λ°©λ²•μœΌλ‘œ prediction을 μ΄μš©ν•˜λŠ” 것을 κ±΄μ˜ν•΄λ³΄κ³  진행해볼 수 μžˆμ„ 것 κ°™λ‹€.

likely(), unlikely() πŸ”—

ν•¨μˆ˜μ˜ 이름 κ·ΈλŒ€λ‘œ, 자주 일어날 λ“―ν•˜κ±°λ‚˜ 자주 μΌμ–΄λ‚˜μ§€ μ•Šμ„ λ“―ν•œ 것을 μœ„ν•œ λ§€ν¬λ‘œμ΄λ‹€. μΆœμ²˜μ—λŠ” μ•„λž˜μ™€ 같은 예제λ₯Ό μ œκ³΅ν•˜κ³  μžˆλ‹€.

1
2
3
4
5
6
bvl = bvec_alloc(gfp_mask, nr_iovecs, &idx);
if (unlikely(!bvl)) {
	mempool_free(bio, bio_pool);
	bio = NULL;
	goto out;
}

νŠΉμ • condition을 ν™•μΈν•˜λŠ” μš©λ„λ‘œ μ‚¬μš©ν•˜λŠ”λ° μœ„μ˜ μ½”λ“œμ—μ„œλŠ” bvec_alloc으둜 ν• λ‹Ήλ°›κ³  bvl이 μœ νš¨ν•œ μ£Όμ†Œκ°’μ΄λΌλ©΄ λ©”λͺ¨λ¦¬ ν•΄μ œλ₯Ό ν•˜κ³  NULL둜 λ³€κ²½ν•˜λŠ” μ½”λ“œμ΄λ‹€.

include/linux/compiler.h νŒŒμΌμ— μ •μ˜λ˜μ–΄ μžˆλŠ” λ§€ν¬λ‘œλ‘œμ„œ branch prediction 을 μœ„ν•œ μš©λ„λ‘œ μ‚¬μš©λœλ‹€. 즉, 결과값이 λŒ€λΆ€λΆ„ false둜 μ˜ˆμƒλœλ‹€λ©΄ unlikely()λ₯Ό, true둜 μ˜ˆμƒλœλ‹€λ©΄ likely()λ₯Ό μ‚¬μš©ν•¨μœΌλ‘œμ„œ 컴파일러λ₯Ό ν†΅ν•œ λΆ„κΈ° μ˜ˆμΈ‘μ„ μ΄μš©ν•˜μ—¬ μ„±λŠ₯ ν–₯상을 κΎ€ν•  수 μžˆλ‹€.

각각의 μ •μ˜λ₯Ό μ‚΄νŽ΄λ³΄λ©΄, μ•„λž˜μ™€ 같이 λ˜μ–΄ μžˆλ‹€.

1
2
#define likely(x)       __builtin_expect(!!(x), 1)
#define unlikely(x)     __builtin_expect(!!(x), 0)

__built-in function πŸ”—

__builtin_expectλ₯Ό μ‚¬μš©ν•˜λŠ” 것은 μ»΄νŒŒμΌλŸ¬μ—κ²Œ λΆ„κΈ° 예츑(branch prediction) 정보λ₯Ό μ œκ³΅ν•˜κΈ° μœ„ν•œ 것이닀. 일반적으둜 κ°œλ°œμžλ“€μ€ μžμ‹ μ˜ ν”„λ‘œκ·Έλž¨μ΄ μ–΄λ–»κ²Œ μˆ˜ν–‰λ˜λŠ”μ§€ μ•ŒκΈ° νž˜λ“€κΈ° λ•Œλ¬Έμ— ‘-fprofile-arcs’ μ˜΅μ…˜μ„ 톡해 ν”„λ‘œνŒŒμΌμ„ ν”Όλ“œλ°± λ°›λŠ” 것을 μ„ ν˜Έν•œλ‹€. ν•˜μ§€λ§Œ μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ— λ”°λΌμ„œ μ΄λŸ¬ν•œ μ˜΅μ…˜μ„ 톡해 ν”„λ‘œνŒŒμΌλ§μ΄ νž˜λ“  κ²½μš°λ„ μžˆλ‹€.

예제 πŸ”—

μ•„λž˜μ˜ 예제λ₯Ό 톡해 μ„±λŠ₯ ν–₯상이 μ–΄λ–»κ²Œ κ°€λŠ₯ν•œμ§€ μ‚΄νŽ΄λ³΄μž.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
#define likely(x)    __builtin_expect(!!(x), 1)
#define unlikely(x)  __builtin_expect(!!(x), 0)

int main(int argc, char *argv[]) {
	int a;

	a = atoi (argv[1]);

	if (unlikely (a == 2))
		a++;
	else
		a--;

	printf("%d\n", a);

	return 0;
}

μœ„ 예제λ₯Ό 컴파일 ν•œ λ‹€μŒ, objdump둜 μ‚΄νŽ΄λ³΄λ©΄ μ•„λž˜μ™€ 같이 main 뢀뢄을 λ°œκ²¬ν•  수 μžˆλ‹€.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
$ gcc -o unlikely unlikely.c
$ objdump -S unlikely


0000000000001149 <main>:
    1149:	55                   	push   %rbp
    114a:	48 89 e5             	mov    %rsp,%rbp
    114d:	48 83 ec 20          	sub    $0x20,%rsp
    1151:	89 7d ec             	mov    %edi,-0x14(%rbp)
    1154:	48 89 75 e0          	mov    %rsi,-0x20(%rbp)
    1158:	48 8b 45 e0          	mov    -0x20(%rbp),%rax
    115c:	48 83 c0 08          	add    $0x8,%rax
    1160:	48 8b 00             	mov    (%rax),%rax
    1163:	48 89 c7             	mov    %rax,%rdi
    1166:	b8 00 00 00 00       	mov    $0x0,%eax
    116b:	e8 d0 fe ff ff       	callq  1040 <atoi@plt>
    1170:	89 45 fc             	mov    %eax,-0x4(%rbp)
    1173:	83 7d fc 02          	cmpl   $0x2,-0x4(%rbp)
    1177:	0f 94 c0             	sete   %al
    117a:	0f b6 c0             	movzbl %al,%eax
    117d:	48 85 c0             	test   %rax,%rax
    1180:	74 06                	je     1188 <main+0x3f>
    1182:	83 45 fc 01          	addl   $0x1,-0x4(%rbp)
    1186:	eb 04                	jmp    118c <main+0x43>
    1188:	83 6d fc 01          	subl   $0x1,-0x4(%rbp)
    118c:	8b 45 fc             	mov    -0x4(%rbp),%eax
    118f:	89 c6                	mov    %eax,%esi
    1191:	48 8d 3d 6c 0e 00 00 	lea    0xe6c(%rip),%rdi        # 2004 <_IO_stdin_used+0x4>
    1198:	b8 00 00 00 00       	mov    $0x0,%eax
    119d:	e8 8e fe ff ff       	callq  1030 <printf@plt>
    11a2:	b8 00 00 00 00       	mov    $0x0,%eax
    11a7:	c9                   	leaveq
    11a8:	c3                   	retq
    11a9:	0f 1f 80 00 00 00 00 	nopl   0x0(%rax)

cmpl %0x2, -0x4(%rbp) μ—μ„œ 보듯 2와 같을 κ²½μš°μ— jump λͺ…λ Ήμ–΄λ₯Ό μˆ˜ν–‰ν•˜κ³  같지 μ•Šμ„ κ²½μš°μ—λŠ” κ³„μ†ν•΄μ„œ λͺ…λ Ήμ–΄λ₯Ό 순차 μ§„ν–‰ν•œλ‹€. je λͺ…λ Ήμ–΄λ₯Ό μ‹€ν–‰ν•˜μ§€ μ•ŠμœΌλ‹ˆ pipeline flushκ°€ μΌμ–΄λ‚˜μ§€ μ•Šμ•„ branch prediction을 ν•˜μ§€ μ•Šμ•˜μ„ λ•Œλ³΄λ‹€ μ„±λŠ₯ ν–₯상을 κΎ€ν•  수 μžˆλ‹€.

λ§Œμ•½, likely()λ₯Ό ν•˜κ²Œ 되면 μ–΄λ–¨κΉŒ? μ•„λ§ˆ λ°˜λŒ€λ‘œ λͺ…λ Ήμ–΄κ°€ 싀행될 것이닀. 즉, ν”„λ‘œκ·Έλž˜λ¨Έκ°€ μ˜ˆμƒν•˜λŠ” μ‹œλ‚˜λ¦¬μ˜€λ‘œ λΆ„κΈ° μ˜ˆμΈ‘μ„ ν•˜μ—¬ μ΅œλŒ€ν•œ jump λͺ…λ Ήμ–΄λ₯Ό μˆ˜ν–‰ν•˜μ§€ μ•Šλ„λ‘ ν•˜λŠ” 기법이닀.

좜처 πŸ”—