Помилка компіляції GCC з> 2 Гб коду


108

У мене величезна кількість функцій на загальну суму близько 2,8 Гб об'єктного коду (на жаль, немає можливості обійтись, наукові обчислення ...)

Коли я намагаюся зв'язати їх, я отримую (очікувані) 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

Будь-які підказки, де шукати проблему?

EDIT: Перш за все, дякую за обговорення ... Щоб уточнити трохи, у мене є сотні функцій (кожен розміром приблизно 1 Мб в окремих об’єктних файлах):

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лише повертає дубль із зовнішньої бібліотеки. Як бачимо, csc[]це попередньо обчислена карта значень, яка також оцінюється в окремих файлах об'єктів (знову ж таки, сотнями розміром приблизно приблизно 1 Мб) наступної форми:

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: Дякую за пропозиції та обговорення досі ... Я спробую якось згорнути петлі при генерації коду, не знаю, як це точно зробити, якщо чесно, але це найкраща ставка.

До речі, я не намагався сховатися за "це наукові обчислення - ніякого способу оптимізації". Просто основа цього коду - це те, що виходить із "чорної скриньки", до якої я не маю реального доступу, і, тим більше, все це чудово спрацювало з простими прикладами, і я в основному відчуваю, що переповнюється тим, що відбувається в реальному світовий додаток ...

EDIT4: Отже, мені вдалося зменшити розмір коду cscвизначень приблизно на четверте, спростивши вирази в системі комп’ютерної алгебри ( Mathematica ). Зараз я бачу певний спосіб зменшити його на інший порядок, застосувавши деякі інші хитрощі перед створенням коду (який би звів цю частину приблизно до 100 Мб), і я сподіваюся, що ця ідея спрацює.

Тепер пов’язані з вашими відповідями: я намагаюся знову повернути петлі назад у funcs, де CAS не дуже допоможе, але у мене вже є деякі ідеї. Наприклад, сортуючи вирази за змінними типу x12, x13,..., розбираємо cscs з Python та генеруємо таблиці, що пов'язують їх між собою. Тоді я можу принаймні генерувати ці частини як петлі. Оскільки це здається найкращим рішенням поки що, я відзначаю це як найкращу відповідь.

Однак я хотів би також дати кредит VJo. GCC 4.6 справді працює набагато краще, створює менший код і швидший. Використання великої моделі працює за таким кодом, як є. Тож технічно це правильна відповідь, але змінити цілу концепцію - набагато кращий підхід.

Дякую всім за ваші пропозиції та допомогу. Якщо хтось зацікавлений, я збираюся опублікувати остаточний результат, як тільки я буду готовий.

ЗАМОВЛЕННЯ. Лише деякі зауваження до деяких інших відповідей: Код, який я намагаюся запустити, не виникає в результаті розширення простих функцій / алгоритмів і нерозумної непотрібної розгортання. Що насправді відбувається, це те, що матеріал, з якого ми починаємо, є досить складними математичними об'єктами, і приведення їх у числово- обчислювальну форму породжує ці вирази. Проблема полягає фактично в основній фізичній теорії. Складність проміжних виразів масштабується фактично, що добре відомо, але, поєднуючи все це з чимось фізично вимірюваним - спостережуваним, воно просто зводиться до лише декількох дуже малих функцій, що складають основу виразів. (У цьому відношенні, безумовно, є щось "неправильне" із загальним і доступним лише для цьогоansatz, яку називають "теорією збурень") Ми намагаємось вивести цей ансац на інший рівень, який вже не є аналітичним, і де основи необхідних функцій не відомі. Тож ми намагаємось це жорстоко змусити. Не найкращий спосіб, але, сподіваємось, той, хто допомагає в нашому розумінні фізики під рукою врешті ...

ОСТАННЕ ВИДАЛЕННЯ: Завдяки всім вашим пропозиціям мені вдалося значно зменшити розмір коду, використовуючи Mathematica та модифікацію генератора коду для funcs дещо уздовж рядків верхньої відповіді :)

Я спростив cscфункції з Mathematica, знизивши її до 92 МБ. Це непридатна частина. Перші спроби тривали назавжди, але після деяких оптимізацій це зараз проходить приблизно за 10 хвилин на одному процесорі.

Вплив на funcs було драматичним: весь розмір коду для них зменшився приблизно до 9 Мб, тому код тепер налічується в діапазоні 100 Мб. Тепер є сенс увімкнути оптимізацію, і виконання відбувається досить швидко.

Ще раз дякую всім за ваші пропозиції, я багато чого навчився.


17
Якщо у вас є стільки даних, вам слід перемістити їх із вихідних файлів, а замість mmapцього самостійно із зовнішнього бінарного файлу під час виконання.
R .. GitHub СТОП ДОПОМОГАЄТЬСЯ

3
Чи можете ви навести приклад однієї (або двох) цих функцій? Це справді виглядає дивно. Ви також можете динамічно завантажувати ці функції за допомогою функції dl *.
Патрік Шлютер

7
@bbtrb: Перший мій інстинкт схожий на R .., це звучить як проблема дизайну. Правда, я не знаю, що є загальним у наукових обчислювальних колах, але я ніколи не чув, щоб хтось намагався зв’язати об’єктний файл розміром 2,8 ГБ або щось віддалено близько до нього, і не впевнений, що GCC справді це підтримає. Чесно кажучи, я б очікував, що будь-який кодовий потік такого розміру буде чистим спагетті.
Микола Найт

46
абсолютно не існує можливості, щоб оптимальне рішення проблеми передбачало 2 Гб об'єктного файлу.
Девід Геффернан

35
не вводьте свої дані в код
Девід Геффернан

Відповіді:


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 chunks або за допомогою файлу, відображеного на пам'ять.

Для вашого конкретного прикладу в func1 собі уявити , як би ви переписати функцію через оцінювач , якщо ви мали доступ до базової адреси sі , cscа також вектор , як уявлення констант і зсувів , які необхідно додати до базових адресами , щоб дістатися до x14, ds8іcsc[51370]

Потрібно створити нову форму "даних", яка опише, як обробляти фактичні дані, які ви передаєте, для вашої величезної кількості функцій.


45

X86-64 ABI використовується Linux визначає «велику» модель спеціально , щоб уникнути таких обмежень по розміру, який включає в себе 64-бітові типи переміщення для ПРТА і PLT. (Дивіться таблицю в розділі 4.4.2 та послідовності інструкцій в 3.5.5, де показано, як вони використовуються.)

Оскільки ваші функції займають 2,8 ГБ, вам не пощастило, оскільки gcc не підтримує великі моделі. Те, що ви можете зробити, - це реорганізувати свій код таким чином, що дозволить вам розділити його на спільні бібліотеки, які ви б динамічно пов'язували.

Якщо це неможливо, як хтось запропонував, замість того, щоб вводити ваші дані в код (компілювати та пов'язувати їх), оскільки він величезний, ви можете завантажувати його під час виконання (або як звичайний файл, або можете скопіювати його).

EDIT

Здається, велика модель підтримується gcc 4.6 (див. Цю сторінку ). Ви можете спробувати це, але вищезазначене все ж стосується реорганізації коду.


Тож, про що ви говорите, це те, що коли я б групував об’єктивні файли в декілька невеликих спільних бібліотек, я би подолав обмеження?
bbtrb

3
@bbtrb Праворуч. Але я б все одно шукав інший спосіб реалізації ваших функцій. Б'юсь об заклад, що ваша компіляція триватиме назавжди
BЈoviћ

18
WTF? Цей код повинен бути згенерований деяким сценарієм; ніхто не пише мегабайт коду вручну! Та ж логіка, що генерує код, також може бути використана для запуску обчислень.
zvrba

6
Я настійно рекомендую спробувати gcc 4.6, дуже ймовірно, що для цієї програми буде створено більш високий код, ніж gcc 4.1; можливо, навіть вдасться вичавити всю річ у 2 Гб, не роблячи нічого розумного, усуваючи проблему (спробуйте комбінації -Os, -fwhole-program та -flto - за допомогою цього обсягу коду оптимізація для розміру є оптимізація для швидкості). Однак, якщо це не допомагає достатньо, ви також повинні знати, що для роботи великої моделі вам доведеться перебудувати принаймні частину бібліотеки С у великій моделі (crt * .o, libc_nonshared.a , і libpthread_nonshared.a).
zwol

1
@bdonlan Статичне посилання - це також можливість.
zvrba

37

У програмі цієї сторони, помилки кешу для коду, швидше за все, перевищують витрати на циклічне виконання під час виконання. Я рекомендую вам повернутися до свого генератора коду і дати йому створити деяке компактне представлення для того, що він оцінює (тобто таке, яке, швидше за все, вміститься в D-кеш), а потім виконати це за допомогою інтерпретатора у вашій програмі. Ви також можете побачити, чи зможете виділити менші ядра, які все ще мають значну кількість операцій, а потім використовувати їх як "інструкції" в інтерпретованому коді.


21

Помилка виникає через те, що у вас занадто багато КОДА, а не даних! На це вказується, наприклад, __libc_csu_fini(яка є функцією), на яку посилається, _startі переїзд обрізається для пристосування. Це означає, що _start(справжня точка входу програми) намагається викликати цю функцію за допомогою ЗНАЧЕНОГО 32-бітного зміщення, яке має лише 2 Гб. Оскільки загальна сума вашого об'єктного коду становить ~ 2,8 ГБ, факти перевіряються.

Якщо ви могли б переробити свої структури даних, велика частина вашого коду могла бути "стиснута", переписавши величезні вирази як прості петлі.

Крім того, ви можете обчислити csc[]в іншій програмі, зберігати результати у файлі та просто завантажувати їх при необхідності.


Чи можете ви навести приклад, як ви переписали б функції простими петлями? Я не стежу за тобою точно. csc[]доводиться обчислювати дуже часто, і я хотів би уникати вводу / виводу диска.
bbtrb

4
@bbtr: Наприклад, для func1вище, що - щось на кшталт: for (int i = 0; i < N; ++i) expr += constants[i].*s.x14*s.x15*csc[49300 + i];.
HighCommander4

@ HighCommander4: абсолютно, я згоден. Це над моєю головою, як створити щось подібне автоматично. Можливо, з окремим масивом, який зберігає індекси ...
bbtrb

2
@bbtrb: Оскільки не існує дивного способу, щоб хтось написав достатньо джерела, щоб вручну створити 2,8 ГБ об'єктного коду, особливо з такими немемонічними іменами символів, повинен бути використаний генератор коду . Робота з цим.
Дональні стипендіати

15

Я думаю, що всі згодні з тим, що потрібно робити інший спосіб робити те, що ти хочеш робити. Компіляція сотень мегабайт (гігабайт?) Коду, пов'язування його у виконуваному мультимігабайтному виконанні та запуску його просто звучить неефективно.

Якщо я правильно зрозумів вашу проблему, ви використовуєте якийсь генератор коду, G, щоб створити купу функцій, func1...Nякі приймають купу карт csc1...Mяк вхідні дані. Що ви хочете зробити - це обчислити csc1...Mта запустити цикл в 1 000 000 разів для різних входів і кожного разу знаходити s = func1 + func2 + ... + funcN. Ви не вказали, як fucn1...Nпов’язані, csc1...Mхоча.

Якщо все це правда, здається, що ви повинні мати можливість повернути проблему на голову по-різному, що потенційно може бути набагато більш керованим і навіть можливо швидшим (тобто, дозволяючи кешу вашої машини фактично функціонувати).

Крім практичної проблеми розмірів об'єктних файлів, ваша поточна програма не буде ефективною, оскільки не локалізує доступ до даних (занадто багато величезних карт) і не має локалізованого виконання коду (занадто багато дуже довгих функцій).

Як щодо розбиття вашої програми на 3 фази: Створення першої фази csc1...Mта їх зберігання. Фаза 2 будує по черзі func, запускайте її 1 000 000 разів з кожним входом і зберігайте результати. На етапі 3 знайдіть суму результатів збережених func1...Nрезультатів за кожний вибіг 1 000 000 разів. Хороша частина цього рішення полягає в тому, що його можна легко зробити паралельним на декількох незалежних машинах.

Редагувати: @bbtrb, чи могли б ви зробити один функціонал та один csc доступними? Вони здаються дуже регулярними і стисливими. Наприклад, func1, здається, є лише сумою виразів, кожен з яких складається з 1 коефіцієнта, 2 індексів змінних в s та 1 індексу в csc. Так його можна зменшити до приємної петлі. Якщо ви робите доступні повні приклади, я впевнений, що можна знайти способи стиснення їх у цикли, а не в довгі вирази.


Так, ви правильно розумієте :) Однак з вашою пропозицією є декілька проблем: 1. Найгірший funcs залежить майже від усіх cscs, і ці числа також повинні бути обчислені 10 ^ 6 разів. 2. Вхід буде отриманий від адаптивного інтегратора Монте-Карло, тобто інтегратор повинен знати повний результат у кожній точці, щоб мати змогу зменшити отриману помилку, уточнивши сітку в районі точки, якщо це необхідно. 3. Великі вирази для cscзбереження ...
bbtrb

1
Так це означає, що ви не можете обчислити cscкожну ітерацію, незалежну від інших? Якби вони були незалежними, ви все одно можете запускати кожен 10 ^ 6 разів і зберігати результати. Однак, якщо серед них є залежності, можливо, вам потрібно з’ясувати, яка з них пов’язана, щось на зразок графіка залежності, а потім спробувати перевірити, чи можна розбити її на кілька незалежних під графіків. Загалом, я думаю, головне - розбити проблему на кілька, незалежних, підпроблем.
AlefSin

5

Якщо я правильно прочитав ваші помилки, те, що змушує вас переносити ліміт, - це ініціалізований розділ даних (якби це був код, ви мали б набагато більше помилок IMHO). Чи є у вас великі масиви глобальних даних? Якщо це так, я б переструктурував програму так, щоб вони були розподілені динамічно. Якщо дані ініціалізуються, я прочитав би їх з файлу конфігурації.

До речі, бачачи це:

(.text + 0x20): невизначене посилання на "main"

Я думаю, у вас є ще одна проблема.


1
Так, ти маєш рацію, дурна помилка, але це не вирішує інших помилок.
bbtrb

3

Мені здається, що код робить чисельну інтеграцію, використовуючи якийсь метод адаптивного глибини. На жаль, генератор коду (а точніше автор генератора коду) настільки дурний , що генерувати одну функцію на патч, а не одну за тип патча. Таким чином, він створює занадто багато коду для компіляції, і навіть якби його можна було скласти, його виконання було б болісним, тому що ніколи нічого не ділиться ніколи. (Чи можете ви уявити біль, викликану завантаженням кожної сторінки об'єктного коду з диска, тому що ніколи нічого не ділиться, і тому він завжди є кандидатом для виселення з ОС. Нічого не говорити про кеші інструкцій, які будуть марними.)

Виправлення полягає в тому, щоб припинити розгортати все; для цього виду коду ви хочете максимально поділитись, оскільки накладні витрати на додаткові інструкції щодо доступу до даних у складніших моделях будуть покриті витратами на обробку (імовірно) великого базового набору даних у будь-якому випадку. Можливо також, що генератор коду навіть зробить це за замовчуванням, і що вчений побачив кілька варіантів розкрутки (зауваживши, що вони іноді покращують швидкість) і ввімкнув їх все відразу і тепер наполягає на тому, що цей безлад буде прийнятий комп'ютером, а не приймати реальні обмеження машини та використовувати числово правильну версію, що генерується за замовчуванням. Але якщо генератор коду цього не зробить, знайдіть той, який буде (або зламати існуючий код).

Підсумок: компілювання та зв’язування 2,8 ГБ коду не працює і не повинно змушувати його працювати. Знайдіть інший спосіб.


3

Пара пропозицій: - Оптимізуйте розмір (-Os). Здійснюйте вбудовані дзвінки функцій, звичайні дзвінки функцій. Увімкнути об'єднання рядків.

Спробуйте розділити речі на різні DLL (спільні об'єкти, .so для Linux, .dylib для Mac OS X). Переконайтесь, що вони можуть бути вивантажені. Потім реалізуйте щось для завантаження речей на вимогу та звільніть їх, коли не потрібно.

Якщо ні, розділіть свій код на різні виконувані файли та використовуйте щось для спілкування між ними (труби, розетки, навіть запис / читання у файл). Незграбний, але які у вас варіанти?

Цілком альтернативно: - Використовуйте динамічну мову з JIT . Прямо над головою - використовуйте LuaJIT - і перепишіть (відновлюйте?) Багато цих виразів у Lua або інших подібних мовах та програмах, які дозволяють збирати код.

LuaJIT досить ефективний, іноді перемагає C / C ++ для певних речей, але часто дуже близький (іноді може бути повільним через поганий збір сміття ще там). Перевірте самі:

http://luajit.org/performance_x86.html

Завантажте scimark2.luaфайл звідти і порівняйте його з версією "С" (google it) - результати часто дуже близькі.


2

Лінкер намагається генерувати 32-бітні компенсації переміщення всередині двійкового файлу, який певним чином перевищив ці обмеження. Спробуйте зменшити вимоги до адресного простору основної програми.

Чи можете ви розділити частину / більшість об'єктного коду на одну або декілька бібліотек (також складених з -fpic / -fPIC)? Потім генеруйте нестатичний двійковий файл, який посилається на ці лібри. Бібліотеки будуть жити в дискретних блоках пам'яті, і ваші компенсації переміщення будуть динамічні / абсолютні (64-бітні), а не відносні (32-бітні).


2

Ці вирази мені дуже схожі на чергування серії. Я не знаю, як виглядає решта коду, але, схоже, не складе труднощів отримати формуючий вираз. Напевно, варто було б це зробити і під час виконання, особливо якщо у вас є 2,8 ГБ 2 КБ розкрученого коду.


1

Це схоже на те, що результат генерації коду пішов не так, можливо, за допомогою символічної алгебри та / або ручної розгортання. Добре відомо, що символічні маніпуляції зростають експоненціально в глибині дерева виразів або обчислювального графіка. Цілком ймовірно, що тут можна використовувати автоматичну диференціацію, що зробить розмір коду досить малим, а також значно прискорить виконання.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.