코드가 2GB 이상인 GCC 컴파일 오류


108

나는 총 2.8GB의 개체 코드에 해당하는 엄청난 수의 기능을 가지고 있습니다 (불행히도 주위에 방법이 없습니다, 과학 컴퓨팅 ...)

링크를 시도 할 때 relocation truncated to fit: R_X86_64_32S컴파일러 플래그를 지정하여 우회하고자하는 (예상 된) 오류가 발생합니다 -mcmodel=medium. 내가 제어하는 ​​것 외에 링크 된 모든 라이브러리는 -fpic플래그 로 컴파일됩니다 .

그래도 오류가 지속되며 링크하는 일부 라이브러리가 PIC로 컴파일되지 않은 것으로 가정합니다.

오류는 다음과 같습니다.

/usr/lib/gcc/x86_64-redhat-linux/4.1.2/../../../../lib64/crt1.o: In function `_start':
(.text+0x12): relocation truncated to fit: R_X86_64_32S against symbol `__libc_csu_fini'     defined in .text section in /usr/lib64/libc_nonshared.a(elf-init.oS)
/usr/lib/gcc/x86_64-redhat-linux/4.1.2/../../../../lib64/crt1.o: In function `_start':
(.text+0x19): relocation truncated to fit: R_X86_64_32S against symbol `__libc_csu_init'    defined in .text section in /usr/lib64/libc_nonshared.a(elf-init.oS)
/usr/lib/gcc/x86_64-redhat-linux/4.1.2/../../../../lib64/crt1.o: In function `_start':
(.text+0x20): undefined reference to `main'
/usr/lib/gcc/x86_64-redhat-linux/4.1.2/../../../../lib64/crti.o: In function    `call_gmon_start':
(.text+0x7): relocation truncated to fit: R_X86_64_GOTPCREL against undefined symbol      `__gmon_start__'
/usr/lib/gcc/x86_64-redhat-linux/4.1.2/crtbegin.o: In function `__do_global_dtors_aux':
crtstuff.c:(.text+0xb): relocation truncated to fit: R_X86_64_PC32 against `.bss' 
crtstuff.c:(.text+0x13): relocation truncated to fit: R_X86_64_32 against symbol `__DTOR_END__' defined in .dtors section in /usr/lib/gcc/x86_64-redhat-linux/4.1.2/crtend.o
crtstuff.c:(.text+0x19): relocation truncated to fit: R_X86_64_32S against `.dtors'
crtstuff.c:(.text+0x28): relocation truncated to fit: R_X86_64_PC32 against `.bss'
crtstuff.c:(.text+0x38): relocation truncated to fit: R_X86_64_PC32 against `.bss'
crtstuff.c:(.text+0x3f): relocation truncated to fit: R_X86_64_32S against `.dtors'
crtstuff.c:(.text+0x46): relocation truncated to fit: R_X86_64_PC32 against `.bss'
crtstuff.c:(.text+0x51): additional relocation overflows omitted from the output
collect2: ld returned 1 exit status
make: *** [testsme] Error 1

그리고 내가 연결하는 시스템 라이브러리 :

-lgfortran -lm -lrt -lpthread

문제를 찾을 수있는 단서가 있습니까?

편집 : 우선, 토론에 감사드립니다 ... 조금을 명확히하기 위해 다음과 같은 수백 가지 기능 (개별 개체 파일의 크기 약 1MB)이 있습니다.

double func1(std::tr1::unordered_map<int, double> & csc, 
             std::vector<EvaluationNode::Ptr> & ti, 
             ProcessVars & s)
{
    double sum, prefactor, expr;

    prefactor = +s.ds8*s.ds10*ti[0]->value();
    expr =       ( - 5/243.*(s.x14*s.x15*csc[49300] + 9/10.*s.x14*s.x15*csc[49301] +
           1/10.*s.x14*s.x15*csc[49302] - 3/5.*s.x14*s.x15*csc[49303] -
           27/10.*s.x14*s.x15*csc[49304] + 12/5.*s.x14*s.x15*csc[49305] -
           3/10.*s.x14*s.x15*csc[49306] - 4/5.*s.x14*s.x15*csc[49307] +
           21/10.*s.x14*s.x15*csc[49308] + 1/10.*s.x14*s.x15*csc[49309] -
           s.x14*s.x15*csc[51370] - 9/10.*s.x14*s.x15*csc[51371] -
           1/10.*s.x14*s.x15*csc[51372] + 3/5.*s.x14*s.x15*csc[51373] +
           27/10.*s.x14*s.x15*csc[51374] - 12/5.*s.x14*s.x15*csc[51375] +
           3/10.*s.x14*s.x15*csc[51376] + 4/5.*s.x14*s.x15*csc[51377] -
           21/10.*s.x14*s.x15*csc[51378] - 1/10.*s.x14*s.x15*csc[51379] -
           2*s.x14*s.x15*csc[55100] - 9/5.*s.x14*s.x15*csc[55101] -
           1/5.*s.x14*s.x15*csc[55102] + 6/5.*s.x14*s.x15*csc[55103] +
           27/5.*s.x14*s.x15*csc[55104] - 24/5.*s.x14*s.x15*csc[55105] +
           3/5.*s.x14*s.x15*csc[55106] + 8/5.*s.x14*s.x15*csc[55107] -
           21/5.*s.x14*s.x15*csc[55108] - 1/5.*s.x14*s.x15*csc[55109] -
           2*s.x14*s.x15*csc[55170] - 9/5.*s.x14*s.x15*csc[55171] -
           1/5.*s.x14*s.x15*csc[55172] + 6/5.*s.x14*s.x15*csc[55173] +
           27/5.*s.x14*s.x15*csc[55174] - 24/5.*s.x14*s.x15*csc[55175] +
           // ...
           ;

        sum += prefactor*expr;
    // ...
    return sum;
}

객체 s는 상대적으로 작고 필요한 상수 x14, x15, ..., ds0, ... 등을 유지하면서 ti외부 라이브러리에서 double을 반환합니다. 보시다시피, csc[]는 다음 형식의 개별 개체 파일 (각각 약 ~ 1MB 크기의 수백 개)에서도 평가되는 미리 계산 된 값 맵입니다.

void cscs132(std::tr1::unordered_map<int,double> & csc, ProcessVars & s)
{
    {
    double csc19295 =       + s.ds0*s.ds1*s.ds2 * ( -
           32*s.x12pow2*s.x15*s.x34*s.mbpow2*s.mWpowinv2 -
           32*s.x12pow2*s.x15*s.x35*s.mbpow2*s.mWpowinv2 -
           32*s.x12pow2*s.x15*s.x35*s.x45*s.mWpowinv2 -
           32*s.x12pow2*s.x25*s.x34*s.mbpow2*s.mWpowinv2 -
           32*s.x12pow2*s.x25*s.x35*s.mbpow2*s.mWpowinv2 -
           32*s.x12pow2*s.x25*s.x35*s.x45*s.mWpowinv2 +
           32*s.x12pow2*s.x34*s.mbpow4*s.mWpowinv2 +
           32*s.x12pow2*s.x34*s.x35*s.mbpow2*s.mWpowinv2 +
           32*s.x12pow2*s.x34*s.x45*s.mbpow2*s.mWpowinv2 +
           32*s.x12pow2*s.x35*s.mbpow4*s.mWpowinv2 +
           32*s.x12pow2*s.x35pow2*s.mbpow2*s.mWpowinv2 +
           32*s.x12pow2*s.x35pow2*s.x45*s.mWpowinv2 +
           64*s.x12pow2*s.x35*s.x45*s.mbpow2*s.mWpowinv2 +
           32*s.x12pow2*s.x35*s.x45pow2*s.mWpowinv2 -
           64*s.x12*s.p1p3*s.x15*s.mbpow4*s.mWpowinv2 +
           64*s.x12*s.p1p3*s.x15pow2*s.mbpow2*s.mWpowinv2 +
           96*s.x12*s.p1p3*s.x15*s.x25*s.mbpow2*s.mWpowinv2 -
           64*s.x12*s.p1p3*s.x15*s.x35*s.mbpow2*s.mWpowinv2 -
           64*s.x12*s.p1p3*s.x15*s.x45*s.mbpow2*s.mWpowinv2 -
           32*s.x12*s.p1p3*s.x25*s.mbpow4*s.mWpowinv2 +
           32*s.x12*s.p1p3*s.x25pow2*s.mbpow2*s.mWpowinv2 -
           32*s.x12*s.p1p3*s.x25*s.x35*s.mbpow2*s.mWpowinv2 -
           32*s.x12*s.p1p3*s.x25*s.x45*s.mbpow2*s.mWpowinv2 -
           32*s.x12*s.p1p3*s.x45*s.mbpow2 +
           64*s.x12*s.x14*s.x15pow2*s.x35*s.mWpowinv2 +
           96*s.x12*s.x14*s.x15*s.x25*s.x35*s.mWpowinv2 +
           32*s.x12*s.x14*s.x15*s.x34*s.mbpow2*s.mWpowinv2 -
           32*s.x12*s.x14*s.x15*s.x35*s.mbpow2*s.mWpowinv2 -
           64*s.x12*s.x14*s.x15*s.x35pow2*s.mWpowinv2 -
           32*s.x12*s.x14*s.x15*s.x35*s.x45*s.mWpowinv2 +
           32*s.x12*s.x14*s.x25pow2*s.x35*s.mWpowinv2 +
           32*s.x12*s.x14*s.x25*s.x34*s.mbpow2*s.mWpowinv2 -
           32*s.x12*s.x14*s.x25*s.x35pow2*s.mWpowinv2 -
           // ...

       csc.insert(cscMap::value_type(192953, csc19295));
    }

    {
       double csc19296 =      // ... ;

       csc.insert(cscMap::value_type(192956, csc19296));
    }

    // ...
}

그게 다예요. 마지막 단계는 모든 것을 호출 func[i]하고 결과를 합산하는 것입니다.

이것이 다소 특별하고 특이한 경우라는 사실에 관하여 : 네, 그렇습니다. 이것은 사람들이 입자 물리학을위한 고정밀 계산을 시도 할 때 대처해야하는 것입니다.

EDIT2 : x12, x13 등이 실제로 상수가 아니라는 것도 추가해야합니다. 특정 값으로 설정되고 모든 함수가 실행되고 결과가 반환되며 다음 값을 생성하기 위해 새로운 x12, x13 등이 선택됩니다. 그리고 이것은 10 ^ 5에서 10 ^ 6 번해야합니다 ...

EDIT3 : 지금까지 제안과 토론을 해주셔서 감사합니다 ... 솔직히 말해서 정확히 어떻게해야할지 모르겠지만 어떻게 든 코드 생성시 루프를 롤업하려고 노력할 것입니다.하지만 이것이 최선의 방법입니다.

BTW, 나는 "이것은 과학적 컴퓨팅이다. 이 코드의 기초는 내가 실제로 접근 할 수없는 "블랙 박스"에서 나오는 것뿐입니다. 게다가 모든 것이 간단한 예제로 훌륭하게 작동했습니다. 그리고 저는 주로 실제에서 일어나는 일에 압도당했습니다. 세계 응용 ...

EDIT4 : 그래서 저는 csc컴퓨터 대수 시스템 ( Mathematica ) 에서 표현을 단순화 하여 정의 의 코드 크기를 약 1/4로 줄일 수있었습니다 . 이제 코드를 생성하기 전에 다른 트릭 (이 부분을 약 100MB로 줄임)을 적용하여 다른 크기로 줄일 수있는 방법도 알고 있으며이 아이디어가 효과가 있기를 바랍니다.

이제 귀하의 답변과 관련이 있습니다. funcCAS가 많이 도움이되지 않는 s 에서 루프를 다시 롤백하려고 시도하고 있지만 이미 몇 가지 아이디어가 있습니다. 예를 들어,와 같은 변수를 기준으로 표현식을 정렬하면 s를 Python으로 x12, x13,...구문 분석하고 csc서로 관련된 테이블을 생성합니다. 그런 다음 적어도 이러한 부분을 루프로 생성 할 수 있습니다. 이것이 지금까지 최선의 해결책 인 것처럼 보이므로 이것을 최선의 답변으로 표시합니다.

그러나 VJo에게도 신용을 부여하고 싶습니다. GCC 4.6은 실제로 훨씬 더 잘 작동 하고 더 작은 코드를 생성하며 더 빠릅니다. 큰 모델을 사용하면 코드에서있는 그대로 작동합니다. 기술적으로 이것은 정답이지만 전체 개념을 변경하는 것이 훨씬 더 나은 접근 방식입니다.

귀하의 제안과 도움에 감사드립니다. 관심이 있으신 분은 준비가되는대로 최종 결과물을 게시하겠습니다.

비고 : 다른 답변에 대한 언급 : 제가 실행하려는 코드는 단순한 함수 / 알고리즘의 확장과 어리석은 불필요한 풀기에서 비롯된 것이 아닙니다. 실제로 일어나는 일은 우리가 시작하는 것은 매우 복잡한 수학적 객체이고 그것들을 수치 적으로 계산 가능한 형태로 가져 오면 이러한 표현이 생성 된다는 것 입니다. 문제는 실제로 근본적인 물리적 이론에 있습니다. 중간 표현의 복잡성은 팩토리얼로 확장되는데, 이는 잘 알려진 사실이지만,이 모든 것을 물리적으로 측정 할 수있는 것으로 결합하면 (관찰 가능한) 표현의 기초를 형성하는 매우 작은 함수 몇 개로 귀결됩니다. (일반적으로 사용할 수 있는이 점에서 "잘못된"것이 있습니다.ansatz ( "perturbation theory"라고 함)) 우리는이 ansatz를 더 이상 분석적으로 실행 불가능하고 필요한 기능의 기초가 알려지지 않은 다른 수준으로 가져 오려고합니다. 그래서 우리는 이것을 이렇게 무차별 대입하려고합니다. 최선의 방법은 아니지만 결국 물리학에 대한 우리의 이해를 돕는 방법 이길 바랍니다.

최종 편집 : 모든 제안 덕분에, 나는 티카와가 코드 생성기의 수정 사용, 상당히 코드 크기를 줄이기 위해 관리했습니다 func상단 응답의 라인을 따라 다소들 :)

cscMathematica로 함수를 단순화하여 92MB로 줄였습니다. 이것은 환원 불가능한 부분입니다. 첫 번째 시도는 오랜 시간이 걸렸지 만 일부 최적화 후 단일 CPU에서 약 10 분 만에 실행됩니다.

에 미치는 영향 func은 극적이었습니다. 전체 코드 크기가 약 9MB로 줄어 들었으므로 이제 코드는 총 100MB 범위에 속합니다. 이제 최적화를 켜는 것이 합리적이며 실행이 매우 빠릅니다.

다시 한 번, 여러분의 제안에 감사드립니다. 많은 것을 배웠습니다.


17
그 정도의 데이터가있는 경우 소스 파일에서 대신 mmap런타임에 외부 바이너리에서 직접 데이터를 이동해야 합니다.
R .. GitHub STOP

3
이러한 기능 중 하나 (또는 ​​두 개)의 예를 들어 주시겠습니까? 정말 이상해 보입니다. dl * 함수를 사용하여 이러한 함수를 동적으로로드 할 수도 있습니다.
Patrick Schlüter 2011 년

7
@bbtrb : 제 첫 본능은 R ..과 비슷합니다. 디자인 문제처럼 들립니다. 물론, 과학계에서 흔한 일이 무엇인지 모르겠지만, 누군가 2.8GB 객체 파일을 연결하려는 사람에 대해 들어 본 적이 없으며, 2.8GB 객체 파일이나 원격으로 그 파일에 가까운 어떤 것도 GCC가 진정으로 지원할 것 같지는 않습니다. 솔직히, 그 크기의 코드 블롭은 순수한 스파게티가 될 것으로 기대합니다.
Nicholas Knight

46
문제에 대한 최적의 솔루션이 2GB의 개체 파일을 포함하는 방법은 전혀 없습니다.
David Heffernan 2011 년

35
데이터를 코드에 넣지 마십시오
David Heffernan

답변:


53

따라서이 텍스트를 생성하는 프로그램이 이미 있습니다.

prefactor = +s.ds8*s.ds10*ti[0]->value();
expr = ( - 5/243.*(s.x14*s.x15*csc[49300] + 9/10.*s.x14*s.x15*csc[49301] +
       1/10.*s.x14*s.x15*csc[49302] - 3/5.*s.x14*s.x15*csc[49303] -...

double csc19295 =       + s.ds0*s.ds1*s.ds2 * ( -
       32*s.x12pow2*s.x15*s.x34*s.mbpow2*s.mWpowinv2 -
       32*s.x12pow2*s.x15*s.x35*s.mbpow2*s.mWpowinv2 -
       32*s.x12pow2*s.x15*s.x35*s.x45*s.mWpowinv2 -...

권리?

모든 함수가 비슷한 "형식"(n 개의 숫자를 m 번 곱하고 결과를 더하거나 비슷한 것을 추가)하면 다음과 같이 할 수 있다고 생각합니다.

  • 생성기 프로그램을 문자열 대신 출력 오프셋으로 변경하십시오 (즉, 문자열 "s.ds0"대신 생성 offsetof(ProcessVars, ds0)
  • 이러한 오프셋의 배열을 만듭니다.
  • 위의 배열과 구조체 포인터의 기본 주소를 받아들이고 결과를 생성하는 평가자를 작성하십시오.

배열 + 평가자는 함수 중 하나와 동일한 논리를 나타내지 만 평가자 만 코드가됩니다. 배열은 "데이터"이며 런타임에 생성되거나 디스크에 저장되어 i 청크 또는 메모리 매핑 파일을 읽을 수 있습니다.

FUNC1의 특정 예를 들어,베이스의 주소에 대한 액세스 권한이 있다면 당신은 평가를 통해 기능을 다시 얼마나 상상 scsc와도 상수와 당신이 얻을 수있는 기본 주소에 추가해야하는 오프셋 (offset)의 표현과 같은 벡터 x14, ds8csc[51370]

수많은 함수에 전달하는 실제 데이터를 처리하는 방법을 설명하는 새로운 형태의 "데이터"를 만들어야합니다.


45

ABI 리눅스 - 64에서 사용은 에 "L 모델"구체적 GOT 및 PLT 64 비트 재배치 타입을 포함하는 이러한 크기의 제한을 피할 수를 정의한다. (섹션 4.4.2의 표와 사용 방법을 보여주는 3.5.5의 명령어 시퀀스를 참조하십시오.)

함수가 2.8GB를 차지하므로 gcc가 대형 모델을 지원하지 않기 때문에 운이 좋지 않습니다. 할 수있는 일은 동적으로 링크 할 공유 라이브러리로 분할 할 수있는 방식으로 코드를 재구성하는 것입니다.

이것이 가능하지 않다면 누군가가 제안했듯이 데이터를 코드에 넣는 대신 (컴파일하고 연결하는 대신), 크기가 크므로 런타임에로드 할 수 있습니다 (일반 파일로로드하거나 mmap 할 수 있음).

편집하다

대형 모델이 gcc 4.6에서 지원되는 것 같습니다 ( 이 페이지 참조 ). 시도해 볼 수 있지만 위의 내용은 코드 재구성에 여전히 적용됩니다.


그래서 당신이 말하는 것은 여러 개의 작은 공유 라이브러리에서 개체 파일을 그룹화하면 한계를 극복 할 수 있다는 것입니다.
bbtrb 2011-06-09

3
@bbtrb 맞아. 그러나 나는 여전히 당신의 기능을 구현하는 다른 방법을 찾고 있습니다. 나는 당신의 편집이 영원히
걸릴 것이라고

18
WTF? 이 코드는 일부 스크립트에 의해 생성되어야합니다. 아무도 손으로 메가 바이트의 코드를 작성하지 않습니다! 코드 를 생성 하는 동일한 논리를 사용 하여 계산 을 실행할 수도 있습니다 .
zvrba 2011 년

6
gcc 4.6을 사용하는 것이 좋습니다.이 프로그램에서 gcc 4.1보다 우수한 코드를 생성 할 가능성이 매우 높습니다. 크기 최적화, 코드의 볼륨 - 심지어 당신의 문제 (-Os의 시도 조합, -fwhole 프로그램 및 -flto을 제거, 영리 아무것도 할 필요없이 2기가바이트에 모든 것을 짜 할 수있을 것 입니다 속도 최적화). 그러나 이것이 충분히 도움이되지 않는 경우, 대형 모델이 작동하려면 대형 모델 (crt * .o, libc_nonshared.a)에서 C 라이브러리의 적어도 일부를 다시 빌드해야합니다. 및 libpthread_nonshared.a).
zwol

1
@bdonlan 정적 연결도 가능합니다.
zvrba

37

그 쪽의 프로그램을 사용하면 코드에 대한 캐시 미스가 런타임에 루핑 비용을 초과 할 가능성이 매우 높습니다. 코드 생성기로 돌아가서 생성하도록 권장합니다. 평가하려는 항목 (즉, D- 캐시에 맞을 가능성이있는 것)에 대한 간결한 표현을 다음 프로그램의 인터프리터로 실행하는 것이 좋습니다. 여전히 상당한 수의 작업이있는 더 작은 커널을 제거 할 수 있는지 확인한 다음이를 해석 된 코드에서 '명령'으로 사용할 수 있습니다.


21

데이터가 아닌 CODE가 너무 많기 때문에 오류가 발생합니다! 이것은 예를 들어 __libc_csu_fini(함수) 참조되는 것으로 표시되고 _start재배치는 적합하도록 잘립니다. 이것은_start (프로그램의 실제 진입 점) 범위가 2GB 인 SIGNED 32 비트 오프셋을 통해 해당 함수를 호출하려고합니다. 개체 코드의 총량이 ~ 2.8GB이므로 사실이 확인됩니다.

데이터 구조를 재 설계 할 수 있다면 거대한 표현식을 간단한 루프로 다시 작성하여 대부분의 코드를 "압축"할 수 있습니다.

또한 csc[]다른 프로그램에서 계산 하고 결과를 파일에 저장하고 필요할 때로드 할 수 있습니다.


간단한 루프로 함수를 다시 작성하는 방법에 대한 예를 제공 할 수 있습니까? 나는 당신을 정확하게 따르지 않습니다. csc[]매우 자주 계산해야하고 디스크 I / O를 피하고 싶습니다.
bbtrb

4
@bbtr : 예를 들어, func1위의 경우 : for (int i = 0; i < N; ++i) expr += constants[i].*s.x14*s.x15*csc[49300 + i];.
HighCommander4 2011 년

@ HighCommander4 : 절대적으로 동의합니다. 이와 같은 것을 자동으로 생성하는 방법에 대한 내 머리 바로 위에 있습니다. 어쩌면 별도의 배열이 저장 지수 ...
bbtrb

2
@bbtrb : 누군가가 손으로 2.8GB의 개체 코드를 생성 할 수있는 충분한 소스를 작성하는 이상한 방법없기 때문에 , 특히 그러한 비 연상 기호 이름으로 코드 생성기를 사용해야합니다 . 그것으로 일하십시오.
Donal Fellows

15

여러분이하고 싶은 일을 할 수있는 다른 방법이 있어야한다는 데 모두가 동의한다고 생각합니다. 수백 메가 바이트 (기가 바이트?)의 코드를 컴파일하고이를 멀티 기가 바이트 크기의 실행 파일에 연결하고 실행하는 것은 매우 비효율적으로 들립니다.

문제를 올바르게 이해하면 일종의 코드 생성기 G를 사용하여 여러 func1...Ncsc1...M을 입력으로 사용 하는 여러 함수를 생성합니다 . 당신이 원하는 것은 계산하고 csc1...M, 다른 입력과 매번 찾을 때마다 1,000,000 번의 루프를 실행하는 것 s = func1 + func2 + ... + funcN입니다. 그래도 어떻게 fucn1...N관련 되는지 지정하지 않았습니다 csc1...M.

모든 것이 사실이라면, 잠재적으로 훨씬 더 관리하기 쉽고 더 빠를 수있는 다른 방식으로 문제를 해결할 수 있어야합니다 (즉, 컴퓨터의 캐시가 실제로 작동하도록하는 것).

객체 파일 크기의 실질적인 문제 외에도 현재 프로그램은 데이터에 대한 액세스를 지역화하지 않고 (너무 많은 거대한 맵) 지역화 된 코드 실행 (너무 많은 매우 긴 함수)이 없기 때문에 효율적이지 않습니다.

프로그램을 3 단계로 나누는 방법 : 1 단계 빌드 csc1...M및 저장. 2 단계 func는 한 번에 하나씩 빌드 하고 각 입력으로 1,000,000 번 실행하고 결과를 저장합니다. 3 단계 func1...N에서는 1,000,000 회 중 각 실행에 대해 저장된 결과 의 합계를 찾습니다 . 이 솔루션의 좋은 점은 여러 독립 시스템에서 쉽게 병렬화 할 수 있다는 것입니다.

편집 : @bbtrb, 하나의 func와 하나의 csc를 사용 가능하게 만들 수 있습니까? 그들은 매우 규칙적이고 압축 가능한 것처럼 보입니다. 예를 들어 func1은 각각 1 개의 계수, s의 변수에 대한 2 개의 인덱스 및 csc에 대한 1 개의 인덱스로 구성된 표현식의 합계 인 것 같습니다. 따라서 멋진 루프로 줄일 수 있습니다. 완전한 예제를 제공한다면 긴 표현이 아닌 루프로 압축하는 방법을 찾을 수있을 것입니다.


예, 올바르게 이해합니다. :) 제안에는 몇 가지 문제가 있습니다. 1. 최악 func의 s는 거의 모든 cscs 에 의존 하며 그 숫자도 10 ^ 6 번 계산되어야합니다. 2. 입력은 적응 형 Monte Carlo 적분기로부터 얻어 질 것입니다. 즉, 적분기는 필요한 경우 포인트 근처의 메시를 미세 조정하여 결과 오류를 줄일 수 있도록 각 포인트에서 전체 결과를 알아야합니다. 3. 대형 표현 csc지속 ...
bbtrb

1
그렇다면 csc각 반복에서 다른 것과 독립적으로 각각 을 계산할 수 없다는 의미 입니까? 독립적 인 경우에도 각각 10 ^ 6 번 실행하고 결과를 저장할 수 있습니다. 그러나 그들 사이에 의존성이 있다면, 의존성 그래프와 같이 어떤 것이 어떤 것과 관련이 있는지 알아 내고이를 여러 개의 독립적 인 하위 그래프로 나눌 수 있는지 확인해야 할 수도 있습니다. 대체로 핵심은 문제를 여러 개의 독립적 인 하위 문제로 나누는 것이라고 생각합니다.
AlefSin 2011 년

5

오류를 올바르게 읽으면 한계를 넘게 만드는 것은 초기화 된 데이터 섹션입니다 (코드라면 훨씬 더 많은 오류 IMHO가 발생합니다). 방대한 글로벌 데이터 배열이 있습니까? 이 경우 동적으로 할당되도록 프로그램을 재구성 할 것입니다. 데이터가 초기화되면 구성 파일에서 읽습니다.

이것을보고있는 BTW :

(.text + 0x20) :`main '에 대한 정의되지 않은 참조

다른 문제가 있다고 생각합니다.


1
예, 어리석은 실수이지만 다른 오류는 해결되지 않습니다.
bbtrb 2011-06-09

3

코드가 일종의 적응 깊이 방법을 사용하여 수치 적분을 수행하는 것처럼 보입니다. 불행히도 코드 생성기 (또는 코드 생성기의 작성자)는 유형 당 하나가 아닌 패치 당 하나의 함수를 생성하는 것이 너무 어리 석습니다. . 따라서 컴파일하기에는 너무 많은 코드가 생성되고 컴파일 될 수 있다고하더라도 어디에도 공유되는 것이 없기 때문에 실행이 고통 스러울 것입니다. (아무것도 공유되지 않았기 때문에 디스크에서 개체 코드의 각 페이지를로드해야하는 고통을 상상할 수 있습니까? 따라서 항상 OS가 제거 할 후보입니다. 쓸모 없게 될 명령 캐시는 말할 것도 없습니다.)

수정 사항은 모든 것을 풀지 않는 것입니다. 이런 종류의 코드의 경우 공유최대화하고 더 복잡한 패턴의 데이터에 액세스하기위한 추가 명령의 오버 헤드가 어쨌든 대규모 기본 데이터 세트를 처리하는 비용으로 흡수되기 때문에 합니다. 코드 생성기가 기본적으로이 작업을 수행 할 수도 있으며 과학자는 언 롤링 옵션 (때때로 속도가 향상된다는 메모 포함)을 확인하고 한꺼번에 모두 켜고이 결과로 인한 혼란을 받아 들여야한다고 주장 할 수도 있습니다. 컴퓨터의 실제 제한을 받아들이고 기본적으로 생성되는 수치 적으로 올바른 버전을 사용하는 대신 컴퓨터에 의해. 그러나 코드 생성기가이를 수행하지 않을 경우 해당 생성기를 가져 오거나 기존 코드를 해킹하십시오.

결론 : 2.8GB의 코드를 컴파일하고 연결하는 것은 작동하지 않으며 강제로 작동해서는 안됩니다. 다른 방법을 찾으십시오.


3

몇 가지 제안 :-크기 최적화 (-Os). 인라인 함수 호출, 일반 함수 호출을 수행하십시오. 문자열 풀링을 활성화합니다.

사물을 다른 DLL (공유 객체, linux의 경우 .so, Mac OS X의 경우 .dylib)으로 분할 해보십시오. 언로드 할 수 있는지 확인하십시오. 그런 다음 필요에 따라로드 할 무언가를 구현하고 필요하지 않을 때 해제합니다.

그렇지 않은 경우 코드를 다른 실행 파일로 분할하고 다른 실행 파일 (파이프, 소켓, 파일 쓰기 / 읽기)을 사용하여 통신하십시오. 어색하지만 어떤 옵션이 있습니까?

완전히 다른 : -에 사용 동적 언어 JIT . 내 머리 바로 위에 LuaJIT를 사용 하고 Lua 또는 코드가 가비지 수집되도록 허용하는 다른 언어 및 런타임 에서 이러한 많은 표현식을 다시 작성 (재생성?)합니다 .

LuaJIT는 매우 효율적이며 때로는 특정 사항에 대해 C / C ++를 능가하지만 종종 매우 가깝습니다 (때로는 가비지 수집 불량으로 인해 느려질 수 있음). 직접 확인 :

http://luajit.org/performance_x86.html

scimark2.lua거기 에서 파일을 다운로드하고 "C"버전 (google it)과 비교합니다. 결과가 매우 유사합니다.


2

링커는 이러한 제한을 초과 한 바이너리 내에서 32 비트 재배치 오프셋을 생성하려고합니다. 기본 프로그램의 주소 공간 요구 사항을 줄여보십시오.

객체 코드의 일부 / 대부분을 하나 이상의 라이브러리로 분할 할 수 있습니까 (-fpic / -fPIC로도 컴파일 됨)? 그런 다음 이러한 라이브러리에 대해 링크하는 비 정적 바이너리를 생성합니다. 라이브러리는 개별 메모리 블록에 있으며 재배치 오프셋은 상대 (32 비트)가 아닌 동적 / 절대 (64 비트)입니다.


2

그 표현은 나에게 번갈아 가며 시리즈처럼 보입니다. 나머지 코드가 어떻게 생겼는지 모르겠지만 생성 표현식을 유도하는 것이 그렇게 어렵지 않은 것 같습니다. 특히 2.8GB의 2KB 언 롤링 코드가있는 경우 실행 시간에도 그만한 가치가있을 것입니다.


1

이것은 아마도 기호 대수 및 / 또는 수동 언 롤링에 의해 코드 생성이 잘못 된 결과처럼 보입니다. 기호 조작은 표현식 트리 또는 계산 그래프의 깊이에서 기하 급수적으로 증가하는 것으로 잘 알려져 있습니다. 여기서 자동 차별화를 사용할 수 있으므로 코드 크기가 매우 작아지고 실행 속도가 크게 빨라집니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.