함수포인터의 성능?

yopeule의 이미지

함수포인터를 써서 함수를 호출하는데 걸리는 시간이

그냥 함수를 호출하는 것에 비해

어느정도의 시간을 더 소요하는지

알 수 있을까요?

변수 콜이나... 조건문이나 연산자 등과 비교해서요.

예를들어 void f()를 함수포인터로 호출하는데 걸리는 시간이 if(x > 0){ a = x }; 를 10번 호출한 것과 같다던지...

jick의 이미지

요즘 컴퓨터의 실행시간은 컴파일러의 최적화, CPU 모델, 캐시 사용 패턴, 기타 무수한 요소에 의해 달라지기 때문에 "x는 y보다 10배 비싸다"와 같은 말은 거의 의미가 없습니다.

(누가 "10배"같이 정확한 숫자로 표현하면 "아 저 사람은 뭘 잘 모르는구나"라고 생각하시면 됩니다.)

함수포인터를 쓰는 게 물론 함수를 직접 호출하는 것보다야 비싸겠지만, 대부분의 경우 그 차이가 전체 프로그램의 성능에 별 영향을 주지 않습니다. 그런 것보다 예를 들면 이진탐색을 할 수 있는 곳에서 순차탐색을 한다든지 하는 문제가 성능에 훨씬 큰 영향을 미칩니다.

그러니까 그냥 프로그램 구조가 논리적으로 함수 포인터를 필요로 하면 이를 이용해서 짜시고 그렇지 않으면 직접 호출하시면 됩니다.

(프로그램을 다 짠 다음에 속도가 느리면 그 때 프로파일을 돌려 봐야 어디서 시간을 잡아먹는지 알 수 있습니다. 그 전에 성능을 신경쓰는 건 아무리 잘해도 추측일 뿐이라 맞을지 틀릴지는 돌려보기 전에 모릅니다.)

yopeule의 이미지

초보라 프로파일...이 뭔지도 잘 모릅니다 ㅠㅠ

아무리 잘해도 추측일 뿐이라... 부질없다는 건 알지만 단순히 호기심이 일어서요.

1. 함수포인터가 매우 느리다는 이야길 본 적이 있습니다.
퀵소트였나? C의 알고리즘에 비교함수를 함수포인터로 받아서 실행되는게 있던데 그게 함수포인터에 의해 엄청나게 느려진다고 하더라고요. 함수 내용이 너무 짧아서 그런 현상이 나타난걸까요?

2. 함수의 호출 속도를 빠르게 하기 위해(?) 자주쓰는 함수는 함수포인터를 통해 호출하라는 얘기도 본 적이 있습니다.
그런데 아무리 캐시에 등록(?)된다고 해도, 함수 포인터가 일반 함수보다 빠른 경우가 존재할 수 있나요???

3. 논리적으로 꼭 필요한 건 아니지만... 그저 제 편의(?)를 위해 switch문 대신 함수포인터배열을 써도 무방할까요? 자주 쓰이는 분기문인데, switch문을 쓸지 함수포인터 배열을 쓸지 고민하는 중입니다.

ymir의 이미지

function pointer 는 indirect call 을 하기 때문에, derefencing 하는 약간의 오버헤드는 있습니다.
그런데, 사실 이것들은 기계들이 알아서 최적화를 하기 때문에, 경우에 따라서의 무의미할 수도 있습니다.
예를 들어 loop 내에서 function pointer 를 call 하는거랑 direct call 하는거랑 비교해 볼 때..
어느정도 유의미한 차이가 있을 거라고 예상되겠지만..
기계가 function pointer 를 한 번 로드해 놓고 계속 direct call 한다면.. 차이는 derefence 딱 한 번 정도 밖에 나지 않게 되겠죠.

물론 단점도 있습니다. function pointer 는 inline 되지 않기 때문에..
1번 qsort 와 같은 경우 자동적으로 최적화가 어려운 걸로 알고 있습니다.
대신 직접 풀어서 direct call 로 바꾸면.. 좀 번거롭더라도 qsort 함수를 가져다 쓰는 것보다 조금 개선할 수도 있는거죠.

이런 특수한 경우를 제외하고는 일반적으로 편리하고 유연하고, 경우에 따라서는 로직을 빠르게 개선할 수 있습니다.

예를 들어 if 문이나 switch 같이 조건식이 좀 길어지는 경우에는...
func_table[condition]->func(); 와 같이 배열로 만들어 호출해 버리면.. branch prediction 이 없기 때문에...
오히려 좀 더 빠르게 함수를 호출할 수 있는 경우가 되는 겁니다.

그 외에도 코드를 직관적으로 만들 수 있고, call back 과 같은 걸 만들어서 쓸 수도 있고.. 하튼 장점이 많기 때문에..
일단은 그냥 쓰고 싶은 대로 쓰세요.

다만 function pointer 로 인해 성능에 관한 이슈를 겪을만한 일은 아마도 거의 없을 것이고..
몇 몇 소스 에디터들은 function pointer 들 trace 잘 못하는 경우도 있어서 불편한 경우가 많으니..
코드를 유연하고 직관적으로, 깔끔하게 만들기 위한 용도로.. 필요한 경우에만 사용하시는게 좋을겁니다.

되면 한다! / feel no sorrow, feel no pain, feel no hurt, there's nothing gained.. only love will then remain.. 『 Mizz 』

yopeule의 이미지

답변 정말 감사합니다!!!!

HDNua의 이미지

1. C에서 지원하는 정렬 함수 중에 제시하신 qsort라는 것이 있습니다.
http://soen.kr/lecture/ccpp/reference/qsort.gif
보시는 바와 같이 4번째 인자로 함수 포인터를 넘기는데, 생각해봅시다.
1) qsort는 재귀적인 함수입니다. 함수 내에서 자기 자신을 호출합니다.
2) 함수는 호출될 때마다 인자 개수만큼의 메모리를 확보합니다.
(실제로는 인자 및 다음 명령의 주소를 먼저 스택에 넣고 함수 위치로 점프하는 형태입니다만)
3) 직접적인 함수 호출은 해당 레이블로 바로 점프할 수 있기 때문에 빠르고,
함수 포인터를 이용한 호출은 포인터로부터 값을 얻어온 후에 그 값으로 점프하는 것이기 때문에
언어적으로만 본다면, 일반적으로 함수 포인터를 이용한 호출이 함수를 직접 호출하는 것보다 느립니다.

qsort가 함수 포인터에 의해 느려진다면, 그 이유는
1) qsort가 재귀적인 함수이므로 매번 인자로 함수 포인터를 넘긴다
2) 따라서 함수 포인터만큼의 메모리를 확보하는 명령어가 추가되어 속도가 느려진다
이렇게 결론을 내릴 수 있습니다.

2. 위에도 말씀드렸지만, 언어적으로 본다면 그런 일은 있을 수 없다고 생각합니다.

3. 함수 호출은 일반적으로 스택을 확보하는 명령도 포함하고 있습니다.
따라서 switch문 대신 함수 포인터를 이용하면 함수 포인터로부터 값을 얻어오는 명령, 함수로 인자를 넣는 명령,
함수를 호출하는 명령, 함수 내부에서 스택을 생성하는 명령, 넣은 인자만큼 스택 포인터를 되돌리는 명령이 추가되기 때문에 속도는 느려집니다.
다만 함수를 쓰는 이유 중에는 코드 길이를 줄이는 목적도 있고, 가독성이나 확장성도 있기 때문에
이를 고려한다면 스위치에 같은 코드를 복사 붙여넣기 하는 것보다는 낫다고 생각합니다.
(근데 그럴 바에야 함수를 직접 호출하는 게 낫지 않나 싶기도 하네요. 굳이 포인터 배열로 만드려면 초기화해야 하고..)

아직 배우는 중인 학생입니다만 의견 남겨봅니다. 틀린 부분 지적해주시면 감사하겠습니다.

저는 이렇게 생각했습니다.

yopeule의 이미지

답변 정말 감사합니다!

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.