-fPIC 플래그는 오버헤드를 얼마나 추가할 수 있습니까?
질문.
나는 Mandelbrot fractal을 계산하는 간단한 코드를 테스트하고 있습니다.포인트가 만델브로 세트에 속하는지 확인하는 기능에서 반복 횟수에 따라 성능을 확인해 왔습니다.놀라운 점은 추가하고 나면 시간 차이가 많이 난다는 것입니다.-fPIC
플래그. 내가 읽은 바로는 보통 오버헤드는 무시할 수 있고 내가 본 최고 오버헤드는 약 6%였습니다.머리 위에서 30% 정도 측정했습니다.어떤 조언이든 감사히 받겠습니다!
나의 프로젝트의 세부사항
사용합니다.-O3
우분투 .04. gcc 4.7.2,투 12.04.2, x86_64 .
#iter C (fPIC) C C/C (fPIC)1 0.01 0.01 1.00100 0.04 0.03 0.75200 0.06 0.04 0.67500 0.15 0.1 0.671000 0.28 0.19 0.682000 0.56 0.37 0.664000 1.11 0.72 0.658000 2.21 1.47 0.6716000 4.42 2.88 0.6532000 8.8 5.77 0.6664000 17.6 11.53 0.66
사용하는 명령어:
gcc -O3 -fPIC fractalMain.c fractal.c -o ffpic
gcc -O3 fractalMain.c fractal.c -o f
코드: fractalMain.c
#include <time.h>
#include <stdio.h>
#include <stdbool.h>
#include "fractal.h"
int main()
{
int iterNumber[] = {1, 100, 200, 500, 1000, 2000, 4000, 8000, 16000, 32000, 64000};
int it;
for(it = 0; it < 11; ++it)
{
clock_t start = clock();
fractal(iterNumber[it]);
clock_t end = clock();
double millis = (end - start)*1000 / CLOCKS_PER_SEC/(double)1000;
printf("Iter: %d, time: %lf \n", iterNumber[it], millis);
}
return 0;
}
코드: fractal.h
#ifndef FRACTAL_H
#define FRACTAL_H
void fractal(int iter);
#endif
코드: fractal.c
#include <stdio.h>
#include <stdbool.h>
#include "fractal.h"
void multiplyComplex(double a_re, double a_im, double b_re, double b_im, double* res_re, double* res_im)
{
*res_re = a_re*b_re - a_im*b_im;
*res_im = a_re*b_im + a_im*b_re;
}
void sqComplex(double a_re, double a_im, double* res_re, double* res_im)
{
multiplyComplex(a_re, a_im, a_re, a_im, res_re, res_im);
}
bool isInSet(double P_re, double P_im, double C_re, double C_im, int iter)
{
double zPrev_re = P_re;
double zPrev_im = P_im;
double zNext_re = 0;
double zNext_im = 0;
double* p_zNext_re = &zNext_re;
double* p_zNext_im = &zNext_im;
int i;
for(i = 1; i <= iter; ++i)
{
sqComplex(zPrev_re, zPrev_im, p_zNext_re, p_zNext_im);
zNext_re = zNext_re + C_re;
zNext_im = zNext_im + C_im;
if(zNext_re*zNext_re+zNext_im*zNext_im > 4)
{
return false;
}
zPrev_re = zNext_re;
zPrev_im = zNext_im;
}
return true;
}
bool isMandelbrot(double P_re, double P_im, int iter)
{
return isInSet(0, 0, P_re, P_im, iter);
}
void fractal(int iter)
{
int noIterations = iter;
double xMin = -1.8;
double xMax = 1.6;
double yMin = -1.3;
double yMax = 0.8;
int xDim = 512;
int yDim = 384;
double P_re, P_im;
int nop;
int x, y;
for(x = 0; x < xDim; ++x)
for(y = 0; y < yDim; ++y)
{
P_re = (double)x*(xMax-xMin)/(double)xDim+xMin;
P_im = (double)y*(yMax-yMin)/(double)yDim+yMin;
if(isMandelbrot(P_re, P_im, noIterations))
nop = x+y;
}
printf("%d", nop);
}
비교 뒷이야기
약간 인위적으로 보일 수도 있습니다.-fPIC
실행 파일을 작성할 때 플래그를 지정합니다(댓글 중 하나에 해당).그래서 몇 가지 설명을 드리겠습니다. 먼저 프로그램을 실행 파일로만 컴파일했고 C에서 is Mandelbrot 함수를 호출하는 Lua 코드와 비교하고 싶었습니다.그래서 저는 lua에서 그것을 부르기 위해 공유 객체를 만들었고 - 그리고 큰 시간 차이가 있었습니다.하지만 왜 그들이 여러 번 반복되면서 성장하는지 이해할 수 없었습니다.결국 그것이 그 때문이라는 것을 알게 되었습니다.-fPIC
. 내 루아 스크립트라고 하는 작은 C 프로그램을 만들 때 (그래서 효과적으로 같은 작업을 수행합니다.) - 시간은 C와 매우 비슷합니다 (그렇지 않으면).-fPIC
지난 며칠 동안 몇 가지 구성으로 확인해 보았는데, 두 가지 매우 유사한 결과가 지속적으로 나타납니다. 바로 다음과 같습니다.-fPIC
속도를 줄이게 될 겁니다
그것은 당신이 다음과 같은 것 없이 컴파일할 때.-fPIC
선택multiplyComplex
,sqComplex
,isInSet
그리고.isMandelbrot
컴파일러에 의해 자동으로 인라인 처리됩니다.이러한 함수를 정적 함수로 정의하면 컴파일 시 동일한 성능을 얻을 수 있습니다.-fPIC
왜냐하면 컴파일러는 인라인을 자유롭게 수행할 수 있기 때문입니다.
컴파일러가 헬퍼 함수를 자동으로 인라인할 수 없는 이유는 기호 인터페이싱과 관련이 있습니다.모든 전역 데이터에 간접적으로 액세스하려면, 즉 전역 오프셋 테이블을 통해 위치에 독립적인 코드가 필요합니다.절차 연결 테이블을 거쳐야 하는 함수 호출에도 동일한 제약 조건이 적용됩니다.런타임에 기호가 다른 기호에 의해 삽입될 수 있으므로( 참조) 컴파일러는 단순히 전역 가시성을 가진 함수를 인라인하는 것이 안전하다고 가정할 수 없습니다.
만약 당신이 다음과 같이 계산하지 않고 컴파일한다면 같은 가정을 만들 수 있습니다.-fPIC
범위가 한 다른 할 수 할 수 즉, , 컴파일러는 검색 범위가 실행 파일 자체에서 시작하여 사전 로드된 라이브러리를 포함한 다른 모든 라이브러리가 뒤따르기 때문에 실행 파일에 정의된 전역 기호를 삽입할 수 없다고 안전하게 가정할 수 있습니다.
보다 자세한 이해를 위해서는 다음 논문을 참조하십시오.
다른 사람들이 이미 지적했듯이-fPIC
은 GCC가 인라인 및 클로닝과 같은 많은 최적화를 비활성화하도록 강제합니다.이를 극복하기 위한 몇 가지 방법을 지적하고자 합니다.
- 교체하다
-fPIC
와 함께-fPIE
컴파일러가 인터포션이 불가능하다고 가정할 수 있는 메인 실행 파일(라이브러리가 아님)을 컴파일하는 경우, - 사용하다
-fvisibility=hidden
그리고.__attribute__((visibility("default")))
라이브러리에서 필요한 기능만 내보내고 나머지 기능은 숨깁니다. 이를 통해 GCC는 숨겨진 기능을 보다 적극적으로 최적화할 수 있습니다. - 개인 기호 별칭 사용(
__attribute__((alias ("__f")));
) 도서관 내에서 도서관 기능을 언급하는 것; 이것은 다시 GCC의 손을 풀어줄 것입니다. - 이전 제안은 다음과 같이 자동화될 수 있습니다.
-fno-semantic-interposition
최근 GCC 버전에 추가된 플래그
은 Clang GCC 롭습니다에 롭습니다. 그것은 그것이 기본적으로 모든 최적화를 허용하기 때문입니다.-fPIC
(다음으로 무시할 수 있음)-fsemantic-interposition
GCC와 유사한 동작을 얻을 수 있습니다.
다른 사람들이 당신의 오프닝 게시글의 댓글란에서 논의한 것과 같이, 다음과 같이 편집합니다.-flto
gcc의 링크 시간 최적화는 몇 가지 함수를 줄이면 실제로 괜찮다는 것을 알 수 있기 때문에, 이 특정한 경우에 볼 수 있는 실행 시간의 차이를 줄이는 데 도움이 될 것입니다;
일반적으로 링크 시간 최적화는 코드 크기를 크게 줄일 수 있으며(~6%), 골드의 링크 시간 최적화에 대한 문서에 링크를 연결하여 실행 시간도 줄일 수 있습니다(프로그램이 캐시에 더 많이 들어감).참고할 점은-fPIC
는 대부분 보다 엄격한 보안을 가능하게 하는 기능으로 간주되며 안드로이드에서는 항상 활성화됩니다.SO에 대한 이 질문도 간략하게 설명합니다.또한, 알려 드리자면,-fpic
의 더 빠른 버전입니다.-fPIC
, 그래서 만약 당신이 사용해야 한다면.-fPIC
해라-fpic
대신 - gcc 문서에 링크합니다.x86의 경우에는 차이가 없겠지만, 직접 확인해보거나 gcc-help에 문의해보셔야 합니다.
언급URL : https://stackoverflow.com/questions/15861759/how-much-overhead-can-the-fpic-flag-add
'programing' 카테고리의 다른 글
AJAX가 뭐지, 정말? (0) | 2023.10.27 |
---|---|
SQL Server(2008)에서 특정 테이블을 사용하는 뷰를 찾는 방법은 무엇입니까? (0) | 2023.10.27 |
타겟팅 위치: 현재 '고임' 상태인 끈적거리는 요소 (0) | 2023.10.27 |
Cannot display HTML string (0) | 2023.10.27 |
PHP를 사용하여 MySQL 데이터베이스 내의 모든 테이블을 표시하시겠습니까? (0) | 2023.10.27 |