vpd 0 24 декабря, 2013 Опубликовано 24 декабря, 2013 · Жалоба В некоторых процессорах, с которыми приходится иметь дело, память уровня L1 может не полностью превращаться в кэш первого уровня. Память L1 намного быстрее обычной пользовательской памяти Linux. в моем случае memcpy, выполненный в обычной памяти (DDR2 SDRAM через кэши L2 и L1) дает скорость около 100 МБ/с. Тот же вызов с указателями в памяти L1 дает скорость более 6 ГБ/c, то есть в 60 раз быстрее. Многие счетные приложения могли бы существенно выиграть, если бы использовали эту память напрямую, а не через кэш. Тем более, что в нашем случае более половины этой памяти (48К из 80К) именно только памятью и являются. Возникла следующая идея - доработать ядро линукс так, чтобы при загрузке процесса в память, оно все секции, начинающиеся с префикса, скажем, ".l1_" (например, ".l1_text"), при возможности (наличии места) переносило само в память L1, и динамически перелинковывало все указатели на новое место. В этом случае программист получает возможность писать приложение как обычно, и только отдельным данным и коду назначать атрибут размещения в секции с другим именем. Собственно, именно так и делается при обычном программировании без Linux. Но загрузчик ELF мог бы сам выделять место в L1, чем гарантировать совместное использование общей памяти разными процессами. Причем, если память L1 в достаточном объеме отсутствует, то ничего страшного не происходило бы, просто в журнал ядро записывало бы предупреждение о невозможности загрузить процесс оптимально. Однако пока я копался в деталях загрузки ELF, уперся в простую проблему. При сборке линкер обычно не делает никаких relocation таблиц, а кладет секции друг за другом в виртуальном адресном пространстве процесса по мере того, как у него проясняется расклад по всем объектным модулям. То есть, перенести отдельную секцию неявно не очень то и получается, надо как-то линкер предупредить, что секция будет динамически линковаться потом, и что нужно составить для нее таблицу символов и поместить в объектный модуль. Так вот, вопрос уперся в то, можно ли такое сделать, и если можно, то как? Еще раз повторю свое видение процесса загрузки такого процесса. 1) Загрузить процесс стандартным образом. 2) Для каждой секции с именем, начинающимся на заданный префикс, выполнить попытку переноса в L1. 3) ... для этого попытаться выделить место в L1, проверить наличие таблицы и при успехе скопировать секцию в L1, перенести все ссылки процесса в новое место. 4) если попытка переноса не удастся, то написать сообщение в журнал ядра. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Harbour 0 24 декабря, 2013 Опубликовано 24 декабря, 2013 · Жалоба Всего-то придется переписать Linux memory manager, добавив свою зону (cat /proc/pagetypeinfo). Ну и скорей всего ld придется патчить, хотя теретически можно использовать и статически привязанные секции. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
vpd 0 24 декабря, 2013 Опубликовано 24 декабря, 2013 · Жалоба Не понял про ld, зачем его патчить? Смысл как раз в том, чтобы динамически перелинковывать часть секций. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Harbour 0 25 декабря, 2013 Опубликовано 25 декабря, 2013 · Жалоба Ну и как тогда предполагается стандартному загрузчику сообщить что этот sysbrk нужно вызывать с параметром для зоны L-cache ? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
vpd 0 25 декабря, 2013 Опубликовано 25 декабря, 2013 · Жалоба ну, а что, просто секцию сделать relocatable нельзя? Ну или как крайний вариант - сделать отдельный объектный модуль, который скомпилировать отдельно как so, и его потом встроить (влинковать) в исполнимый файл. Или стандартно ld может делать либо исполнимый неперемещаемый, либо исполнимый перемещаемый как целое, либо целиком .so? В моем случае патчить ld затруднительно, так как для выбранной архитектуры есть только готовые пресобранные кросс binutils + gcc от CodeSourcery. Исходников нет. Хочется проверить идею где-то на уровне ld command file. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
sasamy 11 25 декабря, 2013 Опубликовано 25 декабря, 2013 · Жалоба В моем случае патчить ld затруднительно, так как для выбранной архитектуры есть только готовые пресобранные кросс binutils + gcc от CodeSourcery. Исходников нет. Ну это неправда, учитывая что TI и Mentor Graphics это не китайщина беспредельная и законы соблюдают http://sourcery.mentor.com/public/gnu_toolchain/ Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
vpd 0 25 декабря, 2013 Опубликовано 25 декабря, 2013 · Жалоба За ссылку спасибо! Но это все же вариант не самый удобный, хотелось бы уложиться в стандартные возможности. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
sasamy 11 25 декабря, 2013 Опубликовано 25 декабря, 2013 · Жалоба хотелось бы уложиться в стандартные возможности. Стандартно SRAM отдают на уровне ядра драйверам быстрой периферии (HS USB например или например в i.mx5/6 для видеопроцессора). Код все равно в кеше исполняется а для данных элементарно смапить эту память на пользовательском уровне, тем более в вашем случае и мапить ничего не надо - MMU нет - лезь куда хочешь. Только я на вашем месте проверил для начала - не используется ли эта SRAM в драйверах. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
vpd 0 25 декабря, 2013 Опубликовано 25 декабря, 2013 · Жалоба Ну вот идея как раз в том и состояла, чтобы не городить драйвер для предоставления L1 прикладным программам, и не делать никакого сложного mmap, а просто написать в объявлении данных что-то типа /* <asm/memory.h> */ #define __L1_data __section(.l1_data) /* user program */ char __L1_data buffer_in_L1[4096]; и все. Собственно, обычная программа под DSP у TI в CCS так и выглядит: - переменная закидывается в специальную секцию - на уровне командного файла линкера секция размещается в определенном блоке памяти. Все что хочется добавить, чтобы ядро могло администрировать выделение этой памяти. по поводу "лезь куда хочешь" есть такие возражения: 1) Если процессов, требующих быстрой памяти, несколько, то кто-то должен быть арбитром. 2) Если такая память выделена своим доморощенным арбитром, то остается проблема передачи указателей на эту память в ядро. В нынешнем виде в ядре c6x функции copy_to_user и copy_from_user, ccылаются на функцию _access_ok, которая проверяет правильность пользовательского указателя. И вот эта функция знает только о внешней памяти L3 (DDR2), поэтому программы будут спотыкаться при попытке передать в ядро данные через L1. Чтобы решить эту проблему, хорошо бы ядру явно обозначить наличие L1. Ну или выключить проверку access_ok, но это породит проблему устойчивости системы. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
sasamy 11 25 декабря, 2013 Опубликовано 25 декабря, 2013 · Жалоба Ну вот идея как раз в том и состояла, чтобы не городить драйвер для предоставления L1 прикладным программам Ну вот идея mmap (man mem) как раз в том чтобы не городить драйверы по поводу "лезь куда хочешь" есть такие возражения: Вам в любом случае придется решить эти же самые "возражения" - независимо от реализации. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
vpd 0 25 декабря, 2013 Опубликовано 25 декабря, 2013 · Жалоба И все же я пока не получил ответа на вопрос, можно ли слинковать ELF с помощью обычного так, чтобы одна секция была перемещаемой? То есть для всех символов из этой секции имелась бы таблица символов, а для всех ссылок на эти символы имелась таблица relocation-ов. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
sasamy 11 25 декабря, 2013 Опубликовано 25 декабря, 2013 · Жалоба И все же я пока не получил ответа на вопрос Я вам нагуглил вместо вас http://blackfin.uclinux.org/doku.php?id=uc...st:on-chip_sram http://elinux.org/Memory_Type_Based_Allocation Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Harbour 0 25 декабря, 2013 Опубликовано 25 декабря, 2013 · Жалоба И все же я пока не получил ответа на вопрос, можно ли слинковать ELF с помощью обычного так, чтобы одна секция была перемещаемой? То есть для всех символов из этой секции имелась бы таблица символов, а для всех ссылок на эти символы имелась таблица relocation-ов. -fPIC делает это для всех .text* секций Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
vpd 0 25 декабря, 2013 Опубликовано 25 декабря, 2013 · Жалоба К сожалению, в этих материалах тоже нет ответа на вопрос о перемещении секций и их сочетании с секциями в обычных данных. никаких совпадений на 'reloc' я там не нашел. Ну вот допустим пример такой: char __L1_data some_string[] = "Example string"; int main() { printf("%s\n", some_string); return 0; } Очевидно, перед вызовом printf компилятор захочет загрузить в регистр адрес строки. Если секция в процессе загрузки процесса переедет, то и адрес строки изменится. То есть, нужно будет не только секцию .l1_data передвинуть, но и в секции .text подправить непосредственные операнды в командах загрузки адреса строки. В архитектуре c6x еще 32-битные данные нельзя загрузить в регистр одной командой, они грузятся двумя половинками по 16 бит. Поэтому и фиксапы будут весьма специфические. Насколько я представляю, они где-то в .rel.dyn должны попасть. Но вот при обычном связывании секция .l1_data будет размещена где-нибудь рядом с .data, вычислены реальные смещения относительно начала процесса, половинки которого будут подправлены при передаче аргументов в printf и в таблицы динамического связывание ничего не попадет. Поэтому секцию то я перенести могу, но работать оно будет по старым адресам. Ни в одном из найденных Вами документов вообще ничего про это не написано. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
sasamy 11 26 декабря, 2013 Опубликовано 26 декабря, 2013 (изменено) · Жалоба -fPIC делает это для всех .text* секций PIC - это прямой и рекомендуемый метод, но существует еще динамическая релокация. То есть, нужно будет не только секцию .l1_data передвинуть, но и в секции .text подправить непосредственные операнды в командах загрузки адреса строки. Не совсем так по крайней мере на архитектурах которые поддерживают динамическую релокацию. Вот наглядная статья, правда на примере x86 и динамических библиотек http://eli.thegreenplace.net/2011/08/25/lo...ared-libraries/ У блэкфинов в ядре есть (или был ?) свой специальный парсер elf который определял что секцию надо помещать в sram, в ванильном ядре этого нет - sram используется для буферов в драйверах. http://lkml.indiana.edu/hypermail/linux/ke...06.2/00159.html правда я не понял - почему они genalloc не используют в качестве аллокатора http://lxr.free-electrons.com/source/lib/genalloc.c Изменено 26 декабря, 2013 пользователем sasamy Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться