Ошибка компиляции 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

Есть подсказки, где искать проблему?

РЕДАКТИРОВАТЬ: Прежде всего, спасибо за обсуждение ... Чтобы немного уточнить, у меня есть сотни функций (каждая размером около 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 действительно работает намного лучше, производит меньше кода и быстрее. Использование большой модели работает с кодом как есть. Так что технически это правильный ответ, но изменение всей концепции - гораздо лучший подход.

Спасибо всем за ваши предложения и помощь. Если кому-то интересно, я опубликую окончательный результат, как только буду готов.

ЗАМЕЧАНИЯ: просто некоторые замечания к некоторым другим ответам: код, который я пытаюсь запустить, не возникает из расширения простых функций / алгоритмов и глупого ненужного развертывания. На самом деле происходит то, что мы начинаем с довольно сложных математических объектов, и приведение их к численно вычислимой форме генерирует эти выражения. Проблема на самом деле заключается в основной физической теории. Сложность промежуточных выражений масштабируется факториально, что хорошо известно, но при объединении всего этого материала с чем-то физически измеримым - наблюдаемым - это просто сводится к небольшому количеству очень маленьких функций, которые составляют основу выражений. (Есть определенно что-то "неправильное" в этом плане с общими и единственно доступнымианзац, который называется «теорией возмущений»). Мы пытаемся вывести этот анзац на другой уровень, который аналитически уже невозможен и где не известен базис необходимых функций. Итак, мы пытаемся использовать его таким образом. Не лучший способ, но, надеюсь, тот, который, в конце концов, поможет нам понять физику ...

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

Я упростил cscфункции с помощью Mathematica, уменьшив его до 92 МБ. Это неприводимая часть. Первые попытки заняли много времени, но после некоторой оптимизации теперь они выполняются примерно за 10 минут на одном процессоре.

Эффект на funcs был драматическим: размер всего кода для них уменьшился примерно до 9 МБ, поэтому теперь общий размер кода составляет 100 МБ. Теперь имеет смысл включить оптимизацию, и выполнение происходит довольно быстро.

Еще раз спасибо всем за ваши предложения, я многому научился.


17
Если у вас так много данных, вы должны переместить их из исходных файлов, а вместо mmapэтого сами из внешнего двоичного файла во время выполнения.
R .. GitHub НЕ ПОМОГАЕТ ICE

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)
  • создать массив таких смещений
  • напишите оценщик, который принимает указанный выше массив и базовые адреса указателей структуры и выдает результат

Оценщик массив + будет представлять ту же логику, что и одна из ваших функций, но только оценщик будет кодом. Массив представляет собой «данные» и может быть либо сгенерирован во время выполнения, либо сохранен на диске и прочитан фрагментами или с файлом, отображаемым в память.

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

Вам необходимо создать новую форму «данных», которая будет описывать, как обрабатывать фактические данные, которые вы передаете огромному количеству функций.


45

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

Поскольку ваши функции занимают 2,8 ГБ, вам не повезло, потому что gcc не поддерживает большие модели. Что вы можете сделать, так это реорганизовать свой код таким образом, чтобы вы могли разделить его на общие библиотеки, которые вы могли бы динамически связывать.

Если это невозможно, как кто-то предложил, вместо того, чтобы помещать ваши данные в код (компилировать и связывать его), поскольку он огромен, вы можете загрузить его во время выполнения (либо как обычный файл, либо вы можете его mmap).

РЕДАКТИРОВАТЬ

Похоже, что большая модель поддерживается gcc 4.6 (см. Эту страницу ). Вы можете попробовать это, но вышесказанное по-прежнему применимо к реорганизации вашего кода.


Итак, вы говорите, что когда я сгруппировал бы объектные файлы в несколько небольших общих библиотек, я бы преодолел ограничения?
bbtrb 09

3
@bbtrb Верно. Но я бы все равно поискал другой способ реализации ваших функций. Бьюсь об заклад, твоя компиляция займет вечность
BЈови

18
WTF? Этот код должен быть сгенерирован каким-то скриптом; никто не пишет мегабайты кода вручную! Та же логика, которая генерирует код, может также использоваться для выполнения вычислений.
zvrba 09

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

1
@bdonlan Возможна также статическая линковка.
zvrba

37

С программой на этой стороне промахи в кэше для кода, скорее всего, превысят затраты на создание цикла во время выполнения. Я бы порекомендовал вам вернуться к своему генератору кода и создать некоторое компактное представление того, что он хочет оценить (то есть, которое может поместиться в D-кеш), а затем выполнить это с помощью интерпретатора в вашей программе. Вы также можете посмотреть, можете ли вы исключить меньшие ядра, которые все еще имеют значительное количество операций, а затем использовать их как «инструкции» в интерпретируемом коде.


21

Ошибка возникает из-за того, что у вас слишком много КОДА, а не данных! На это указывает, например __libc_csu_fini, ссылка (которая является функцией), _startи перемещение усекается, чтобы соответствовать. Это означает, что_start (истинная точка входа программы) пытается вызвать эту функцию через 32-битное смещение SIGNED, которое имеет диапазон только 2 ГБ. Поскольку общий объем вашего объектного кода составляет ~ 2,8 ГБ, факты подтверждаются.

Если бы вы могли перепроектировать свои структуры данных, большую часть вашего кода можно было бы «сжать», переписав огромные выражения в виде простых циклов.

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


Не могли бы вы привести пример того, как бы вы переписали функции с помощью простых циклов? Я не совсем слежу за тобой. csc[]приходится вычислять очень часто, и я бы хотел избежать дискового ввода-вывода.
bbtrb 09

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

@ HighCommander4: абсолютно согласен. Это просто выше моей головы, как создать что-то подобное автоматически. Может быть, с отдельным массивом, в котором хранятся индексы ...
bbtrb 09

2
@bbtrb: Так как никто, черт возьми, не написал достаточно исходного кода для создания 2,8 ГБ объектного кода вручную, особенно с такими немнемоническими именами символов, должен был использоваться генератор кода . Работайте с этим.
Donal Fellows

15

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

Если я правильно понимаю вашу проблему, вы используете какой-то генератор кода, G, для генерации набора функций, func1...Nкоторые принимают на csc1...Mвходе набор карт . Что вы хотите сделать, так это вычислить csc1...Mи запустить цикл 1000000 раз для разных входных данных и каждый раз найти s = func1 + func2 + ... + funcN. Вы не указали, как fucn1...Nсвязаны с csc1...M.

Если все это правда, кажется, что вы сможете перевернуть проблему с ног на голову иным способом, который потенциально может быть намного более управляемым и даже, возможно, быстрее (т.е. позволяя кешу вашей машины действительно функционировать).

Помимо практической проблемы размеров объектных файлов, ваша текущая программа будет неэффективной, поскольку она не локализует доступ к данным (слишком много огромных карт) и не имеет локализованного выполнения кода (слишком много очень длинных функций).

Как насчет разбиения вашей программы на 3 этапа: сборка на этапе 1 csc1...Mи их сохранение. Фаза 2 строит по очереди func, запускает 1000000 раз с каждым вводом и сохраняет результаты. На этапе 3 найдите сумму результатов сохраненных func1...Nрезультатов для каждого прогона из 1000000 раз. Преимущество этого решения в том, что его можно легко сделать параллельно на нескольких независимых машинах.

Изменить: @bbtrb, не могли бы вы когда-нибудь сделать доступными один func и один csc? Они кажутся очень регулярными и сжимаемыми. Например, func1 кажется просто суммой выражений, каждое из которых состоит из 1 коэффициента, 2 индексов переменных в s и 1 индекса в csc. Так что это можно свести к красивому циклу. Если вы сделаете полные примеры доступными, я уверен, что можно найти способы сжать их в циклы, а не в длинные выражения.


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

1
Значит ли это, что вы не можете рассчитывать cscкаждую итерацию независимо от других? Если бы они были независимыми, вы все равно могли бы запускать каждый из них 10 ^ 6 раз и сохранять результаты. Однако, если между ними есть зависимости, возможно, вам нужно выяснить, какая из них связана с какой, что-то вроде графа зависимостей, а затем попытаться посмотреть, можно ли разбить его на несколько независимых подграфов. В общем, я думаю, что главное - разбить проблему на несколько независимых подзадач.
AlefSin

5

Если я правильно прочитал ваши ошибки, то, что заставляет вас переносить лимит, является раздел инициализированных данных (если бы это был код, у вас было бы гораздо больше ошибок, ИМХО). У вас есть большие массивы глобальных данных? В таком случае я бы реструктурировал программу так, чтобы они распределялись динамически. Если данные инициализированы, я бы прочитал их из файла конфигурации.

Кстати, видя это:

(.text + 0x20): неопределенная ссылка на `main '

Думаю, у вас другая проблема.


1
Да, вы правы, глупая ошибка, но остальные ошибки она не решает.
bbtrb 09

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файл оттуда и сравните его с версией "C" (погуглите) - часто результаты очень близки.


2

Компоновщик пытается сгенерировать 32-битные смещения перемещения в двоичном файле, который каким-то образом превысил эти ограничения. Попробуйте уменьшить требования к адресному пространству основной программы.

Можете ли вы разделить часть / большую часть объектного кода на одну или несколько библиотек (также скомпилированных с помощью -fpic / -fPIC)? Затем сгенерируйте нестатический двоичный файл, который связывается с этими библиотеками. Библиотеки будут располагаться в дискретных блоках памяти, и ваши смещения перемещения будут динамическими / абсолютными (64-разрядные), а не относительными (32-разрядные).


2

Для меня эти выражения очень похожи на чередующуюся серию. Я не знаю, как выглядит остальная часть кода, но не похоже, что вывести генерирующее выражение будет так сложно. Вероятно, оно того стоит и во время выполнения, особенно если у вас 2,8 ГБ развернутого кода 2 КБ.


1

Это похоже на неправильный результат генерации кода, возможно, из-за символической алгебры и / или ручного развертывания. Хорошо известно, что символические манипуляции экспоненциально растут в глубине дерева выражений или вычислительного графа. Вполне вероятно, что здесь можно использовать автоматическое дифференцирование, которое сделало бы размер кода довольно маленьким, а также значительно ускорило бы выполнение.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.