programing

인라인 함수 v. 매크로 in C -- 오버헤드(메모리/속도)는 얼마입니까?

powerit 2023. 7. 22. 10:31
반응형

인라인 함수 v. 매크로 in C -- 오버헤드(메모리/속도)는 얼마입니까?

는 스택 오버플로를 검색하여 함수와 같은 매크로와 인라인 함수의 장단점을 찾았습니다.

C에서 서로 다른 매크로 기능 / 인라인 방식에 대한 찬반 토론을 찾았습니다.

하지만 그건 제가 질문한 가장 중요한 질문에 대한 답이 아니었습니다.

즉, 메모리 사용 및 실행 속도 측면에서 매크로 함수(변수, 다른 함수 호출 포함)와 인라인 함수를 사용할 때의 오버헤드는 얼마입니까?

오버헤드에 컴파일러 의존적인 차이가 있습니까?저는 icc와 gcc 둘 다 제 마음대로 합니다.

내가 모듈화하고 있는 코드 조각은 다음과 같습니다.

double AttractiveTerm = pow(SigmaSquared/RadialDistanceSquared,3);
double RepulsiveTerm = AttractiveTerm * AttractiveTerm;
EnergyContribution += 
   4 * Epsilon * (RepulsiveTerm - AttractiveTerm);

제가 인라인 함수/매크로로 변환하는 이유는 c 파일에 삭제한 다음 유사하지만 약간 다른 함수/매크로를 조건부로 컴파일할 수 있기 때문입니다.

예:

double AttractiveTerm = pow(SigmaSquared/RadialDistanceSquared,3);
double RepulsiveTerm = pow(SigmaSquared/RadialDistanceSquared,9);
EnergyContribution += 
   4 * Epsilon * (RepulsiveTerm - AttractiveTerm);

(두 번째 줄의 차이에 유의하십시오...)

이 기능은 내 코드의 중심 기능이며 프로그램에서 한 단계당 수천 번 호출되며 프로그램은 수백만 단계를 수행합니다.따라서 저는 가능한 한 오버헤드를 최소화하고 싶기 때문에 인라인 v. 코드를 매크로로 변환하는 데 드는 오버헤드에 대해 걱정하느라 시간을 낭비하고 있습니다.

이전 논의를 바탕으로 매크로의 다른 장단점(유형 독립성 및 그로 인한 오류)을 이미 인식하고 있습니다.하지만 제가 가장 알고 싶고, 현재는 모르는 것은 공연입니다.

당신들 중 일부 C 참전용사들이 나에게 훌륭한 통찰력을 줄 것이라는 것을 알고 있습니다!!

인라인 함수를 호출하면 일반적으로 매우 적은 양의 오버헤드가 발생하는 함수 호출이 생성되거나 생성되지 않을 수 있습니다.정확한 상황은 다음과 같습니다.inline됩니다. 작은 함수를 , (활성화되었을 때) 할 . ( 제로실함화됩다니따인. 대부분의 함수는 작은 함수를 인라인화하기 위해 선의의 노력을 기울입니다(최소한 최적화가 활성화되었을 때). 하지만 그렇게 할 필요는 없습니다(C99, § 6.7.4).

함수를 인라인 함수로 만드는 것은 함수 호출이 가능한 한 빠르다는 것을 의미합니다.이러한 제안이 효과적인 범위는 구현으로 정의됩니다.

매크로는 이러한 오버헤드를 발생시킬 가능성이 적습니다. (하지만 컴파일러가 어떤 작업을 수행하는 것을 막을 수 있는 것은 거의 없습니다. 표준은 컴파일된 프로그램의 관찰 가능한 동작만을 정의하지 않습니다.)

더 깨끗한 것을 사용하세요.프로필.그게 중요하다면, 다른 것을 하세요.

또한 Fizzer가 말한 바와 같이, 전력(및 분할)에 대한 호출은 일반적으로 함수 호출 오버헤드보다 더 비쌉니다.이를 최소화하는 것이 좋은 시작입니다.

double ratio = SigmaSquared/RadialDistanceSquared;
double AttractiveTerm = ratio*ratio*ratio;
EnergyContribution += 4 * Epsilon * AttractiveTerm * (AttractiveTerm - 1.0);

아이즈EnergyContribution이렇게 생긴 용어들로만 구성된 건가요?만약 그렇다면, 당김4 * Epsilon반복당 두 배를 저장합니다.

double ratio = SigmaSquared/RadialDistanceSquared;
double AttractiveTerm = ratio*ratio*ratio;
EnergyContribution += AttractiveTerm * (AttractiveTerm - 1.0);
// later, once you've done all of those terms...
EnergyContribution *= 4 * Epsilon;

매크로는 실제로 기능이 아닙니다.당신이 매크로로 정의한 것은 무엇이든 컴파일러가 그것을 보기 전에 프리프로세서에 의해 당신의 코드에 구두로 게시됩니다.프리프로세서는 코드를 더 잘 구성하기 위해 다양한 추상화를 가능하게 하는 소프트웨어 엔지니어 도구일 뿐입니다.

인라인 함수 또는 컴파일러가 알고 있으며 이 함수를 사용하여 수행할 작업에 대한 결정을 내릴 수 있습니다.사용자가 줄을 섰습니다.inline키워드는 단지 제안일 뿐이며 컴파일러는 이를 무시할 수 있습니다.대부분의 경우 더 나은 코드를 얻을 수 있는 것은 이러한 오버라이드입니다.

컴파일러가 함수를 인식하는 또 다른 부작용은 컴파일러가 특정 결정을 내리도록 강제할 수 있다는 것입니다. 예를 들어 코드 인라인을 비활성화하여 코드를 더 잘 디버그하거나 프로파일링할 수 있습니다.인라인 기능을 사용하는 경우와 매크로를 사용하는 경우에는 다른 많은 사용 사례가 있을 수 있습니다.

매크로는 매우 강력하지만, 이를 뒷받침하기 위해 구글 테스트와 구글 모의실험을 인용하겠습니다.매크로를 사용하는 데는 여러 가지 이유가 있습니다.

함수를 사용하여 함께 연결된 간단한 수학 연산은 특히 함수가 변환 단계에서 한 번만 호출되는 경우 컴파일러에 의해 인라인화되는 경우가 많습니다.따라서 컴파일러가 키워드 제공 여부에 관계없이 인라인 결정을 내리는 것은 놀라운 일이 아닙니다.

그러나 컴파일러가 그렇지 않으면 코드의 세그먼트를 수동으로 플랫화할 수 있습니다.만약 당신이 그것을 평평하게 한다면, 매크로는 결국 "실제" 함수와 유사한 의미론을 제시하는 좋은 추상화 역할을 할 것입니다.

크룩스

따라서 컴파일러가 더 나은 물리적 코드를 생성할 수 있도록 특정 논리적 경계를 인식하기를 원합니까? 아니면 수동으로 또는 매크로를 사용하여 컴파일러에 강제 결정을 내리시겠습니까?그 산업은 전자 쪽으로 기울어져 있습니다.

이 경우 매크로를 사용하는 경향이 있습니다. 매크로가 빠르고 더럽기 때문에 더 많은 것을 배울 필요가 없습니다.그러나 매크로는 소프트웨어 엔지니어링 추상화이고 컴파일러가 생성하는 코드에 관심이 있기 때문에 문제가 조금 더 발전한다면 C++ 템플릿을 사용할 것입니다.

제거하려는 것은 pow()에 대한 호출입니다.이 함수는 일반 부동 소수점 지수를 사용하며 적분 지수로 올리기에는 비효율적입니다.이러한 통화를 예로 대체합니다.

inline double cube(double x)
{
    return x * x * x;
}

여기서 성능을 크게 변화시킬 수 있는 유일한 요소입니다.

함수와 같은 매크로를 포함한 매크로는 단순한 텍스트 대체이므로 매개 변수에 주의하지 않으면 엉덩이를 물 수 있습니다.예를 들어, 매우 인기 있는 SQUARE 매크로는 다음과 같습니다.

#define SQUARE(x) ((x)*(x))

만약 당신이 그것을 다음과 같이 부른다면 일어날 것을 기다리는 재앙이 될 수 있습니다.SQUARE(i++)또한 함수와 같은 매크로는 범위 개념이 없으며 로컬 변수를 지원하지 않습니다. 가장 인기 있는 해킹은 다음과 같습니다.

#define MACRO(S,R,E,C)                                     \
do                                                         \   
{                                                          \
  double AttractiveTerm = pow((S)/(R),3);                  \
  double RepulsiveTerm = AttractiveTerm * AttractiveTerm;  \
  (C) = 4 * (E) * (RepulsiveTerm - AttractiveTerm);        \
} while(0)

물론, 이런 결과를 부여하는 것은 어렵습니다.x = MACRO(a,b);.

정확성유지관리성의 관점에서 최선의 선택은 기능을 만들고 다음을 명시하는 것입니다.inline매크로는 기능이 아니므로 매크로와 혼동해서는 안 됩니다.

이를 완료한 후에는 성능을 측정하고 실제 병목 현상이 발생한 후 이를 해킹할 수 있습니다.pow합리화를 위한 후보가 될 것입니다.)

보안 및 버그 유발 측면에서 매크로 및 인라인 기능에 대해 이야기하는 CERT Secure 코딩 표준을 검토하십시오. 함수와 유사한 매크로를 사용하는 것을 권장하지 않습니다. 왜냐하면 : - 프로파일링 감소 - 추적 가능성 감소 - 디버깅하기 어려움 - 심각한 버그로 이어질 수 있기 때문입니다.

질문에 답변하는 가장 좋은 방법은 테스트 데이터를 사용하여 두 가지 접근 방식을 모두 벤치마킹하여 애플리케이션에서 실제로 어떤 것이 더 빠른지 확인하는 것입니다.성능에 대한 예측은 가장 거친 수준을 제외하고는 신뢰할 수 없는 것으로 악명 높습니다.

그렇긴 하지만, 매크로와 진정한 인라인 함수 호출 사이에는 큰 차이가 없을 것으로 예상합니다.두 경우 모두 후드 아래에 동일한 어셈블리 코드가 있어야 합니다.

이것을 무작위로 일시 중지하면, 아마도 100%(엡실론을 뺀 시간)가 내부에 있다는 것을 알게 될 것입니다.pow기능, 그래서 그것이 어떻게 거기에 도달했는지는 기본적으로 아무런 차이가 없습니다.

만약 당신이 그것을 발견했다고 가정한다면, 가장 먼저 해야 할 일은 전화를 없애는 것입니다.pow스택에서 찾은 것입니다. (일반적으로, 그것이 하는 일은log 번째에 두 , 첫 번 째 인 수 인 번 에 수 곱 하 고 째 두 의 곱 하 고 , ▁of 에 인 수 , ▁multiply ▁it,exp또는 같은 일을 하는 무언가.log그리고.exp많은 산술 연산을 포함하는 어떤 종류의 시리즈에 의해 잘 될 수 있습니다.물론 특별한 경우를 찾기는 하지만, 여전히 당신이 하는 것보다 더 오래 걸릴 것입니다.그것만으로도 속도가 어느 정도 빨라질 것입니다.

그런 다음 무작위 일시 중지를 다시 수행합니다.이제 여러분은 많은 시간이 걸리는 다른 것을 보게 될 것입니다.저는 그것이 무엇이 될지 추측할 수 없고, 다른 사람들도 추측할 수 없지만, 당신은 아마도 그것을 줄일 수 있을 것입니다.더 이상 할 수 없을 때까지 계속하세요.

매크로를 사용하도록 선택하는 과정에서 발생할 수 있으며 인라인 기능보다 약간 빠를 수 있습니다.그것은 당신이 그곳에 도착했을 때 판단하기 위한 것입니다.

다른 사람들이 말했듯이, 그것은 대부분 컴파일러에 의존합니다.

어떤 인라인이나 매크로보다 "pow" 비용이 더 많이 든다고 장담합니다 :)

매크로보다는 인라인 기능이 더 깨끗하다고 생각합니다.

캐슁 및 파이프라인은 최신 프로세서에서 이 기능을 실행할 경우 좋은 이점을 얻을 수 있는 곳입니다.즉, 'if'와 같은 분기문을 제거하면 엄청난 차이가 발생합니다(여러 가지 트릭으로 수행할 수 있음).

컴파일러를 쓰는 몇몇 사람들이 이해하기로는 일단 함수를 내부에서 호출하면 코드가 인라인화될 가능성은 거의 없습니다.하지만, 그렇기 때문에 매크로를 사용하면 안 됩니다.매크로는 정보를 제거하고 컴파일러에 최적화할 수 있는 옵션을 훨씬 적게 제공합니다.멀티패스 컴파일러와 전체 프로그램 최적화를 사용하면 코드 인라인화로 인해 분기 예측이 실패하거나 캐시 누락 또는 기타 블랙 매직으로 인해 현대 CPU가 빠르게 작동한다는 것을 알게 됩니다.어쨌든 위의 코드가 최적이 아니기 때문에 거기에 초점을 맞춰야 한다는 지적은 모두가 옳다고 생각합니다.

언급URL : https://stackoverflow.com/questions/5226803/inline-function-v-macro-in-c-whats-the-overhead-memory-speed

반응형