Комментарии 11
RWX память сегодня это почти такая же древность, как и этот ваш ПЛ1. Времён червей Морриса, когда все исполнялось, да ещё по тем же спмчюым адресам на всех машинах.
Запихните скелет обратно в чулан. На дворе 21 век. Концепции W^X уже много лет, а в SELinux аж три типа ограничения на создание исполняемой памяти.
Но ведь JIT в jvm работает при включенном SELinux. Страница помечается как RW, патчится, и потом снова в режим RX переводится.
JIT доступен не везде. И работает он в JVM не всегда так. Например в андроиде AOT, и маппится целиком сбилженный ELF.
Далее, джиту необязательно иметь RWX. Можно сначала RW, на время еодогенерации. Затем RX. Для статьи это означает прыжки в ядро на каждое создание массива, с модификацией таблицы страниц, и ещё синхронизацию между этим.
Далее, JIT на самом деле плохой пример, т.к.позволяет обходить целые комплексы мер безопасности. Например в Андроиде его использовали для удаленной компрометации, которая стала практически невозможной другими средствами. А Эпл недавно пропачила сафари, закрыв удобную лазейку с обходом подписанных указателей. Так что ссылаться на джит не комильфо. А то что автор предлагает — вообще мрак.
обращение к массивам с «динамическими» границами выполняется существенно медленнее, чем к массивам с границами-константами
Вы измеряли, какое ускорение дает ваш метод? Предполагаю, что на фоне вычислений с плавающей запятой и нелокального доступа к памяти (B[K, J]
) на больших матрицах оно будет ничтожно.
Без кодогенерации, но со статическими и динамическими границами, инструкции отличаются:
https://gist.github.com/PlushBeaver/6c0903cc8432fe2e9dfe2cbfdd51b4e4
Я не настоящий сварщик, но кажется, что статистически значимой разницы нет:
Wilcoxon rank sum exact test
data: data$V1 and data$V2
W = 468, p-value = 0.7973
alternative hypothesis: true location shift is not equal to 0
Работаю в области embedded и видел подобное, однако основная часть железяк в данный момент на ARM, где смещение может вычисляться кучей способов, чаще всего предварительной загрузкой соответствующих констант из постоянной памяти в регистры.
Так что для архитектуры ARM данные извращения откровенно бесполезны, ибо патчить память либо бинарник не имеет никакого смысла, нужные константы не фигурируют напрямую в коде, они загружаются однократно перед вычислением смещений.
Я не особо силён в ассемблере x86, но сомневаюсь, что вычисление смещений — это исключительно константы в хард-коде в стиле
imul rdi,I,800
Как минимум, руками это точно можно переписать на аналогичную ARM схему.
Например, если размер массива был 90, а новый 270, то раньше в инструкции размер мог помещаться в 1 байт, а новый размер уже нет.
Аналогично с умножениями на 8,9 — их можно оптимизировать через LEA, а при замене на 13, код разваливается…
Аналогично с умножениями на 8,9
Меня всегда немного смущали float'ы в качестве индексов массивов...
значок «*» просто заменяет на некоторые «некруглые» значения границ. Это сделано для того, чтобы далее в процессе компиляции создавались обычные команды для массивов с границами-константами. А «некруглые» значения не позволяют оптимизатору применять более короткие формы команд, поскольку тогда невозможно скорректировать их другими, например, большими значениями.
Поэтому память для массивов с «динамическими» границами должен явно выделять программист из «кучи» оператором ALLOCATE
А что мешает выделять плоский массив и вычислять индекс вручную как i*w + j
?
Модификация исполняемого кода как способ реализации массивов с изменяемым границами