Процессор Ultrascale. Содержит 4 ядра Cortex A53 и 2 ядра "реального времени" R5. Памяти 2 ГиБ. И ещё ПЛИС для обработки сигналов.
Система Petalinux. Для неё память ограничена:
Shell
# cat /proc/cmdline
earlycon console=ttyPS0,115200 clk_ignore_unused root=/dev/mmcblk1p2 mem=1792M rw rootwait
Написал простейшую программу для запуска на процессоре R5:
Код: Выделить всё
volatile int *a=(int *)0x70008000;
int main() {
while(1)
(*a)++;
}
Код: Выделить всё
if(argc==1) {
int dh=open("/dev/mem",O_RDWR|O_SYNC);
a = mmap(NULL, 128, PROT_READ|PROT_WRITE, MAP_SHARED, dh, 0x70008000);
} else {
int id_md=shmget(100, 128, 0666 | IPC_CREAT));
a=(int *)shmat(id_md,0,0);
}
Для того, чтобы знать быстродействия инкремента ячейки написал программу с таким кодом:
Код: Выделить всё
#define MASK 0x00800000
while(1) {
do {
vt=(*a)&MASK;
} while(vt==vp);
clock_gettime(0,&tt);
dif=(tt.tv_sec-tp.tv_sec)+((tt.tv_nsec-tp.tv_nsec)*1e-9);
printf(" %d %8.5f -> %.4f\n",!!vt,dif,MASK/dif/1000000);
tp=tt; vp=vt;
}
Получил такие результаты.
Программа, работающая на R5 инкриментирует ячейку примерно 34 млн. раз в секунду.
Та же программа, работающая под Linux делает это всего 6.2 млн.
Ячейку в разделяемой памяти этот же код инрементирует со скоростью 266 млн. раз в секунду. Разница почти в 43 раза.
Решил оптимизировать цикл (заменил b .L6 на b .L61 (то есть единица добавляется не к самой ячейке, а только к значению, которое записывается в эту ячейку):
Код: Выделить всё
.L6:
adrp x0, a
add x0, x0, :lo12:a
ldr x0, [x0]
ldr w1, [x0]
.L61:
add w1, w1, 1
str w1, [x0]
b .L61
Аналогичная оптимизация программы для Cortex R5 дало увеличение быстродействия с 34 млн до практически 100.
Почему может быть такая разница в быстродействии?
P.S. Используемые компиляторы:
aarch64-linux-gnu-gcc для компиляции linux=программы для ядра A53 и arm-none-eabi-gcc для компиляции автономной программы для ядра R5 (компиляция напрямую не проходит, компилирую с -c, а потом собираю с помощью arm-none-eabi-ld)