Pull to refresh
32
0
Send message

Да, как раз график SNR и убрали, остальное есть. В debug информации тоже не нашел.

Упс, это я наврал с трейсроутом, впн был через Австрию подключен. Вот правильный

traceroute to 159.223.130.136 (159.223.130.136), 64 hops max, 52 byte packets

 1  starlinkrouter (192.168.1.1)  80.506 ms  2.901 ms  3.156 ms

 2  136.22.97.33 (136.22.97.33)  163.111 ms  112.612 ms  35.243 ms

 3  136.22.254.44 (136.22.254.44)  143.633 ms  174.254 ms  157.615 ms

 4  ae46-0-xcr1.fix.cw.net (195.89.98.65)  176.609 ms  39.401 ms  289.743 ms

 5  ae17.pcr1.fnt.cw.net (195.2.20.226)  40.037 ms

    if-ae-55-2.tcore2.pvu-paris.as6453.net (80.231.245.6)  143.583 ms  157.497 ms

 6  if-ae-49-2.tcore1.pvu-paris.as6453.net (80.231.153.20)  354.200 ms  303.408 ms  178.307 ms

 7  if-ae-55-2.tcore1.pye-paris.as6453.net (80.231.154.30)  178.084 ms

    if-ae-11-2.tcore1.pye-paris.as6453.net (80.231.153.50)  126.836 ms  163.887 ms

 8  prs-bb2-link.ip.twelve99.net (62.115.114.98)  177.876 ms *

    prs-bb1-link.ip.twelve99.net (62.115.123.13)  131.409 ms

 9  ldn-bb4-link.ip.twelve99.net (62.115.133.238)  55.420 ms

    ldn-bb4-link.ip.twelve99.net (62.115.114.228)  56.924 ms

    ldn-bb1-link.ip.twelve99.net (62.115.135.24)  63.724 ms

10  nyk-bb2-link.ip.twelve99.net (62.115.113.20)  127.517 ms

    nyk-bb1-link.ip.twelve99.net (62.115.112.244)  126.303 ms

    if-be-2-2.ecore1.n75-newyork.as6453.net (66.110.96.62)  126.239 ms

11  if-ae-57-2.tcore1.n75-newyork.as6453.net (66.110.96.58)  125.457 ms

    if-ae-14-2.tcore3.nto-newyork.as6453.net (63.243.186.16)  127.999 ms

    if-ae-57-2.tcore1.n75-newyork.as6453.net (66.110.96.58)  134.261 ms

12  if-be-2-2.ecore1.n75-newyork.as6453.net (66.110.96.62)  126.626 ms

    66.110.96.26 (66.110.96.26)  127.960 ms  125.873 ms

13  138.197.244.6 (138.197.244.6)  130.627 ms * *

14  * * *

15  * * *

16  * * *

17  * 159.223.130.136 (159.223.130.136)  128.828 ms  125.300 ms

traceroute

traceroute to 159.223.130.136 (159.223.130.136), 64 hops max, 52 byte packets

 1  10.1.0.1 (10.1.0.1)  69.259 ms  69.228 ms  55.661 ms

 2  94.198.41.209 (94.198.41.209)  74.706 ms  59.823 ms  63.216 ms

 3  37.120.220.142 (37.120.220.142)  74.306 ms  84.343 ms  152.816 ms

 4  vlan2910.bb2.vie1.at.m247.com (82.102.29.30)  65.869 ms  107.932 ms  65.613 ms

 5  win-b2-link.ip.twelve99.net (62.115.146.18)  80.092 ms  77.679 ms  82.097 ms

 6  win-bb3-link.ip.twelve99.net (62.115.114.184)  160.339 ms  163.365 ms  159.595 ms

 7  ffm-bb2-link.ip.twelve99.net (62.115.138.22)  160.000 ms  167.966 ms

    ffm-bb1-link.ip.twelve99.net (62.115.137.202)  152.954 ms

 8  * prs-bb2-link.ip.twelve99.net (62.115.122.138)  152.577 ms  148.584 ms

 9  ldn-bb1-link.ip.twelve99.net (62.115.135.24)  82.147 ms  87.854 ms

    ldn-bb4-link.ip.twelve99.net (62.115.114.228)  79.340 ms

10  nyk-bb1-link.ip.twelve99.net (62.115.112.244)  146.408 ms

    nyk-bb2-link.ip.twelve99.net (62.115.113.20)  148.321 ms  157.793 ms

11  nyk-b3-link.ip.twelve99.net (62.115.115.9)  151.642 ms  150.373 ms

    nyk-b3-link.ip.twelve99.net (62.115.139.151)  148.823 ms

12  digitalocean-ic306498-nyk-b3.ip.twelve99-cust.net (62.115.45.10)  159.121 ms  152.511 ms

    digitalocean-ic306497-nyk-b3.ip.twelve99-cust.net (62.115.45.6)  149.473 ms

Неделю назад пришёл терминал (Польша). Работает стабильно 300/30 Mbit/s.

Пользователя из группы wheel.
fallocate -l 8G /swapfile сработает быстрее чем dd
HISTORY
The gzip program was originally written by Jean-loup Gailly, licensed under the GNU Public Licence.
Matthew R. Green wrote a simple front end for NetBSD 1.3 distribution media, based on the freely re-distributable redistributable
distributable zlib library. It was enhanced to be mostly feature-compatible with the original GNU gzip
program for NetBSD 2.0.

This implementation of gzip was ported based on the NetBSD gzip, and first appeared in FreeBSD 7.0.

~ uname
Darwin
~ gzip --version
Apple gzip 264.50.1

lorca@defaultvps:$ uname 
Linux
lorca@defaultvps:$ gzip --version
gzip 1.6
Copyright (C) 2007, 2010, 2011 Free Software Foundation, Inc.
Copyright (C) 1993 Jean-loup Gailly.
This is free software.  You may redistribute copies of it under the terms of
the GNU General Public License <http://www.gnu.org/licenses/gpl.html>.
There is NO WARRANTY, to the extent permitted by law.

Written by Jean-loup Gailly.
Вот способ по скорости сопоставимый с версией использующей таблицу на 1Mb но без таблицы. Не очень простой для понимания, но быстрый и без дополнительной памяти
Наконец руки дошли проверить на старом RaspberryPi c armv6(ARM1176JZ-S). Он не суперскалярный, single-issue и поэтому более короткий цикл там работает быстрее.
despace(buffer, N)                      :  9.34 ns per operation
despace_ptr(buffer, N)                  :  8.03 ns per operation


Примечательно так же то, что gcc 7.1.1 не сгенерировал оптимальный код, только clang 4. Gcc почему-то постеснялся использовать
strbhs     r1, [ip]!, #0x1
, а вместо этого сгенерировал 2 инструкции
strbhi     r3, [r2]
addhi      r2, r2, #0x1
В первом варианте запись и сравнение не зависят друг от друга, а зависят только от ldrb. При этом strb из того же регистра, в который идет ldrb может начаться на такт раньше, чем другие инструкции, зависящие от этого регистра.

Во втором случае запись зависит от сравнения, и не может начинаться раньше, чем выполнилось сравнение, которое в свою очередь дожидается результата ldrb. Вот и вся разница, счетчик либо указатель тут не причем.

Оптимизированный вариант neon_despace_branchless не зависит от процента пробелов.
Финальная расстановка точек. Тест на Cortex A7. Результаты по скорости:

despace(buffer, N)                      :  4.21 ns per operation
despace_ptr(buffer, N)                  :  5.25 ns per operation
neon_despace(buffer, N)                 :  3.33 ns per operation
neon_despace_branchless(buffer, N)      :  3.69 ns per operation

Где dspace это:
  size_t i = 0, pos = 0;
  while (i < howmany) {
    const char c = bytes[i++];
    bytes[pos] = c;
    pos += (c > 32 ? 1 : 0);
  }
  return pos;

dspace_ptr:
  char *i = bytes, *pos = bytes;
  const char *end = bytes + howmany;
  while (i < end) {
    register char c = *i++;
    if (c>' ') { *pos++ = c;}
  }
  return pos - bytes;


Как видно из результатов код с меньшим количеством инструкций выполняется медленнее. Подробное объяснение потянет на отдельную статью, но если кратко, то важно не только количество инструкций, но и зависимости между ними, и это то, что компилятор умеет выстраивать достаточно не плохо, если ему не мешать. Например на Cortex A7 пара ldr/str для одного и того же регистра выполняется столько же, сколько простой ldr.

Также
addhi      r0, r0, #0x1
subs       r1, r1, #0x1
выполнятся за 1 такт потому что поддерживается dual issue для инструкций читающих по одному регистру.

Вот так, примерно, будет выглядеть выполнение кода по тактам:
1 ldrb r2, [r3]!, #0x1
2 strb r2, [ip, r0]
3 cmp r2, #0x20
4 addhi r0, r0, #0x1
4 subs r1, r1, #0x1
5 bne loc_10554

1 ldrb r1, [r3]!, #0x1
3 cmp r1, #0x21
4 strbhs r1, [ip]!, #0x1
5 cmp r3, r2
6 blo loc_10584


Дизассемблер



Выводы.
  • Оригинальная функция из статьи написана оптимальным образом
  • Не надо мешать компилятору оптимизировать код
  • Оптимизация с использованием NEON имела смысл
Мне кажется что на Cortex A15 не будет разницы по скорости выполнения межу strhib r2, [ip], #1 и strhib r2, [ip]; addhi ip, ip, #1. А на Cortex A7 скорее всего будет, это я чуть позже проверю.

В ARM64 больше нету условного выполнения каждой инструкции, есть b, и csel.
Вот для arm с gcc. 9я строчка, strb ip, [r0, r3], одна команда адресации со смещением.

Вот arm64, 11я строчка csinc для примера из статьи и 49я csel и 45я mov для if.
Вариант из статьи на x86_64 тоже будет оптимальнее на многих компиляторах. Только для варианта из статьи clang 4.0 дополнительно развернул цикл
На обычном ARM индексирование тоже не стоит времени. LDR (register offset). Последний вариант чуть быстрее, но все еще хуже способа из статьи.
despace(buffer, N): 0.79 ns per operation
despace3(buffer, N): 1.19 ns per operation

if вместо тернарного оператора генерирует код через csel + move вместо csinc, что делает цикл на одну инструкцию больше (7 vs 6). Вообще заменять работу с массивами и индексами на указатели — только мешать компилятору оптимизировать.
Поскольку в статье речь идет об arm64 то и скорость я сравнивал на arm64.
Вот результаты:
despace(buffer, N): 0.79 ns per operation
despace2(buffer, N): 1.40 ns per operation
1) Превращение индекса в указатель занимает 0 инструкции (ldrsb w10, [x9], #0x1)
2) Безусловная запись быстрее чем условная, т.к. нет лишнего условного перехода.
3) Проверка генерирует дополнительный условный переход. в то время как тернарный оператор дает одну безусловную инструкцию cinc x0, x0, gt.
В итоге во втором варианте больше ветвлений, которые портят конвейер.
Вот картинки из дизассемблера


И еще там есть замечательная инструкция COMPACT, которая делает то, что тут эмулируется через таблицу
Должна решаться еще лучше, в SVE есть gather-scatter доступ к памяти, который тут и эмулируется.

Information

Rating
Does not participate
Location
Минск, Минская обл., Беларусь
Registered
Activity