call by pointer 와 call by value 의 속도 차이가 유의미한가요?

wogkr3654의 이미지

안녕하세요, c언어 공부중에 있고 임베디드 시스템에 적용하려고 합니다.

c언어는 call by reference 가 없고, call by pointer / value 방식이 존재한다고 하는데,
두 방식으로 함수를 구현할 때,
구조체 1개의 멤버로 value들을 집어넣어 매개변수를 구조체 주소 하나만 넘기는 경우와
구조체로 만들지 않고 여러개의 매개변수를 바로 넣는 경우, 저는 당연히 call by pointer가
더 빠를 것이라고 예상했는데요, 시간 측정을 해보니 실제로는 call by value 방식이
더 빠르던데, 이건 개발 환경에 따라서 달라질수 있는건가요??

찾아봐도 보통 call by reference의 연산 속도 향상에 대한 글들만 있고 call by pointer와
비교한 글들은 없는 것 같아서 질문 올립니다.

매개변수는 총 8개 입니다.

jick의 이미지

이건 안타깝지만 그때그때 다르기 때문에 정답이 없습니다.

포인터로 넘길 경우의 장점은 물론 구조체 전체를 복사하지 않아도 된다는 거죠. 구조체의 크기가 클 경우에는 이게 큰 장점입니다. 예를 들어 string이라면 (일반적으로 말해서) 프로그램을 짤 때에는 이게 몇십 바이트인지 몇십 메가바이트인지 알 도리가 없기 때문에, 경우에 따라 복사의 비용이 엄청나게 커질 수 있습니다.

포인터를 쓰지 않고 통짜로 복사할 경우의 가장 큰 장점은, 구조체 데이터가 다 복사되었기 때문에 컴파일러 입장에서 이 구조체의 내용을 자기가 완전히 컨트롤하고 있다는 것입니다. 그 결과 여러 가지 최적화가 가능해질 수 있습니다. 지나치게 단순한 예제지만, 예를 들어 봅시다.

https://gcc.godbolt.org/z/zWziaQ

struct S {
    int x;
};
 
int f(S &s, int &y) {
    for (int i = 0; i < 100; i++) s.x += y;
    return s.x;
}
 
int g(S s, int y) {
    for (int i = 0; i < 100; i++) s.x += y;
    return s.x;
}

함수 g는 s.x와 y를 한번씩 읽은 다음에 (이미 레지스터에 들어 있습니다) 100을 곱해서 더하면 끝입니다.

반면 함수 f는 100번을 계속 y를 메모리에서 읽어오고, s.x를 읽어온 다음, 다시 더해서 s.x에 넣어야 합니다. 100을 곱해서 한번에 더하면 틀린 코드가 됩니다. 왜냐 하면, 컴파일러 입장에서 이 함수를 이렇게 안 불렀다는 보장이 없는 거죠:

S s;
...
f(s, s.x);

물론 이 경우는 어느 쪽이 더 좋은지 너무나 뻔하지만 (4바이트짜리 구조체를 포인터로 넘길 이유가 없죠), 구조체 크기가 몇십 바이트 정도 된다 하면 애매해지죠. 실제로 돌려보기 전엔 알기 힘듭니다. 아니, 실제로 돌려 봐도 알기 힘듭니다. 자기가 돌리고 있는 그 상황이 정확히 실제 유저들이 사용할 그 상황이라는 보장이 안 되서리...

wogkr3654의 이미지

알려주신 링크로 확인해보니, call by pointer 와 call by value 의 차이는 매개변수의 값을 불러올 때
함수 내부에서 불러오냐 외부에서 불러오는지에 따른 차이밖에 없군요.
친절히 답변해주셔서 감사합니다.

ifree의 이미지

구조체 1개의 멤버로 값들을 집어넣어 매개변수를 구조체 주소 하나만 통채로 넘긴다 해도, 어차피 함수에서 각 값들을 일일히 호출해야 한다면 빨라질 이유가 없습니다.

wogkr3654의 이미지

그냥 가독성에 따라 선택하면 되겠네요. 답변 감사합니다!

bushi의 이미지

x86(32bit) 처럼 죄다 스택에 값을 적어서 넘겨야하는 abi 를 사용할 수 밖에 없는 기계에서야 왼쪽궁뎅이와 우측둔부 정도의 차이겠지만,
레지스터에 값을 담아 넘길 수 있는 기계와 abi 에서는 약간 달라질 수도 있긴 할 것 같습니다.
물론, 받아쓰는 함수가 어떻게 생겨먹었는지에 따라 case by case 이겠지만, 최소한 더 느려질 이유는 없을 것 같아요.

wogkr3654의 이미지

답변 감사드립니다 !!

댓글 달기

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
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.