Pull to refresh
4
0
Send message

У меня получилось сжать переведённую "Войну и Мир" обычным RLE вне зависимости от числа повторений, попробуйте Энтропийное кодирование для потока битовых флагов.

p=2.45%
theoretical limit=66453.89161197383
rANS= 66477
rANS inefficiency=0.03%
origin=3202320
result=3190338
factor=0.37%

Вот код. Вроде бы и немного (21+18 строк), но он довольно таки ёмок на математику, легко допустить ошибку. Если будет несложно дополните статью, так она станет гораздо информативнее.

Максимально дубовая реализация монтгомери вместе с делением по Лемиру улучшила мой результат с 27,223 до 21,820 . Даже обидно как-то, получается раньше я вообще не в ту сторону смотрел. Но теперь до первых мест рукой подать, скорее всего можно те же вызовы _mullo_epi32 в два раза реже делать (у меня на 1 mulmod 3 simd умножения, из которых только два полноценное, и одно урезанное), или от бранча для переполнения вычитания как-то отказаться, его обработка съедает четверть всего времени. Теоретически можно оптимально распланировать умножения по битам степени, и вместо маскировки делать их только тогда когда нужно, это тоже может дать до трети всего времени (умножаем только на половину всех битов).

Да, проверяю по 4 числа одновременно. Главное заранее отсекать большую часть работы (5/6) проверкой на делимость на маленькие делители, довольно красиво сделано, но видимо можно сделать лучше, я использовал для больших libdivide_u32_do_vec256, а для маленьких (2,3,5,7) сообразил трюк с _mm256_shuffle_epi8. Тоже в восторге от результатов первой тройки. Ах да, еще нужно чтение через mmap организовать, в справке от сайта есть пример.

О, я примерно тем же путём шел когда решал https://highload.fun/tasks/10

Правда у меня в итоге векторизованная где-то в 2 раза быстрее не векторизованной, но и другие трюки использовал. Обязательно поделитесь результатом.

а с чего это вы взяли

Все так говорят (на один символ отправка 8 байт если между ними меньше ~20ms), пробежал по коду и не вижу ничего противоречащего этому. Тестить правда лень, если хотите оспорить — wireshark/tcpdump вам в помощь.

подмешивается немного мусора

Действительно в прошлом году появился патч и опция в конфиге, мне интересно, а в вашем дистрибутиве есть эта опция? (проще всего проверить man ssh_config; /Obf)

Презентация про ssh, тут статья. Текст об этом на хабре, но я не рекомендую ни комментарии ни статью: там какая-то отсебятина про visual feedback.

Но в таком случае происходит утечка данных не только о тайминге нажатий, но и о количестве клавиш, что соответствует длине пароля

Вместе с таймингом утекает и длина пароля, ответных пакетов со стороны сервера не нужно.

В комментариях тоже какая-то дичь, например: (проблема не в комментарии или в комментаторе, а в том что его никто не поправил, так и висит).

в SSH автоматически включается Nagel's и передаваемые символы начинают группироваться и объединяться, что портит хакерам весь праздник

/* Informs that the current session is interactive.  Sets IP flags for that. */

void
ssh_packet_set_interactive(struct ssh *ssh, int interactive, int qos_interactive, int qos_bulk)
{
    ...
	set_nodelay(state->connection_in);
    ...
}

/* disable nagle on socket */
void
set_nodelay(int fd)
{
    ...
    if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &opt, sizeof opt) == -1)
		error("setsockopt TCP_NODELAY: %.100s", strerror(errno));
}

Статья про анализ серверного "пинга" со стороны собеседника в IM.

Напишу на тот случай если кто-то не понимает какую конкретно безопасность обеспечивает ‎E2EE и для/от кого. Для любого мессенджера с моментальной доставкой сообщений и без серьёзного "замусоривания" траффика легко понять кто с кем общается используя глобальное наблюдение (без MitM) и элементарные корреляции.

Пусть пользователь A, B живут в стране, где некие вредоносные агенты Е установили специальное оборудование сохраняющее метаданные всего оконечного трафика на всех провайдерах связи. Пусть агенты E знают A, но не знают B, про B известно что он один из множества U.

Теперь каждый раз когда A пишет сообщение B, он инициирует обмен сетевым трафиком с серверами напрямую (Telegram), через peer-to-peer сеть(Tor), либо даже с использованием туннеля с дополнительным шифрованием ( Wireguard или OpenVPN). Но во всех популярных любительских сценариях использования (за редким исключением вроде i2p) размеры пакетов меняются крайне предсказуемо, а то и не меняются вовсе. Теперь E, зная паттерны трафика нового сообщения (а в случае push уведомлений можно опираться и на ip-подсеть как на показатель пуша), запоминает текущее время.

Затем это сообщение должно прийти B, где ситуации повторится. Так как множество людей из U могут получить подобный трафик случайно, E может лишь ограничить размер множества U - даже для довольно таки большого окна доставки в минуты (типично для пуш-уведомлений) с каждым сообщением размер U будет сокращаться в разы, если не в десятки. Для однозначного установления B потребуется около 27 бит информации (|U|~=1.4e8), что вполне себе достижимо при регулярном общении. Даже если утекать будут малые доли бита (т.е. агенты E очень не уверены в том что произошло общение), из того что нам их нужно собрать буквально десятки, при достаточном количестве сообщений легко вычислить весь граф общения.

Эту картину не меняет даже вменяемый false-positive (пусть например фоном запущенный ютуб раз в 15 секунд даёт картину похожую на сообщение, тогда мы должны учесть шанс того что A ничего не отправлял). В таком случае мы не выкидываем кандидатов из U, а честно обновляем ожидания по Байесу. Если проделать подобное в итоге получатся что граф общения оказывается (ребро между вершинами если они общаются) равен попарной временной корреляции "интересного" трафика относительно U.

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

Да, это вычислительно сложная задача, но явно не сложнее подсчета условного PageRank-a для поискового индекса с MapReduce, естественно считать в лоб (O(|U|^2)) нельзя.

Слайды про утечку пользователя по паролю при наборе его используя SSH (не совсем в тему, но идея похожая)

Определение местоположения пользователя популярных "защищенных" мессенджеров

Тут исследователи не пользуются глобальным мониторингом траффика, смотрят только на раундтрипы оповещения о доставке.

P.S.
Задумался над тем что бы комментарий до статьи добить, но об подобном на хабре уже писали еще в 2011 (в контексте Tor, Tarzan и Morphmix).

Еще я сомнительным способом генерировал случайное целое, uniform_uint64() % (HI-LO) + LO В районе 10^18 там уже значительный перекос в пользу меньших чисел.

Было бы любопытно узнать, как график ведёт себя на бесконечности

Прогнал Монте-Карло на равномерных неупорядоченных парах, (это не точно учтёт пары где x=y, но так как их немного, погрешность должна быть небольшой).

Просто взял p:=cnt_good/cnt_iters; estimate:=81*10^{d-2}*p/2;

Скорость симуляции получилась около 5 миллиардов итераций в секунду, что не впечатляет. Пришлось немного попотеть что бы правильно работать с 36-значными числами.

Monte-Carlo
# [x y]
# d=d elapsed_time p_good estimate_pairs
# [269 581]
# d=3 129.385 3.851820e-04 1.559987e+02
# [4395 8691]
# d=4 154.701 8.392064e-05 3.398786e+03
# [87365 79139]
# d=5 155.051 2.766043e-05 1.120248e+05
# [775100 162389]
# d=6 154.746 1.113085e-05 4.507995e+06
# [2530020 4761510]
# d=7 207.304 5.262449e-06 2.131292e+08
# [85693413 36003975]
# d=8 233.018 2.778503e-06 1.125294e+10
# [345731723 932322371]
# d=9 234.242 1.595132e-06 6.460286e+11
# [8388016499 5721446594]
# d=10 237.009 9.736462e-07 3.943267e+13
# [40264350366 98521508913]
# d=11 237.098 6.248657e-07 2.530706e+15
# [919177426937 734068423163]
# d=12 237.305 4.179230e-07 1.692588e+17
# [8616586083842 7797719745830]
# d=13 267.747 2.884882e-07 1.168377e+19
# [45126923716086 53984469270216]
# d=14 270.713 2.058496e-07 8.336909e+20
# [204357829294211 514926408573260]
# d=15 269.294 1.502094e-07 6.083479e+22
# [6896406641595237 8139155118610023]
# d=16 319.639 1.116254e-07 4.520827e+24
# [62459283066899325 52619943312077259]
# d=17 343.897 8.466919e-08 3.429102e+26
# [409783614423487398 781679240519529663]
# d=18 344.870 6.535767e-08 2.646985e+28

Относительная точность падает при уменьшении p, поэтому оценку для d=18 получилось посчитать с точностью ±0.3%

Monte-Carlo
Monte-Carlo

Hidden text
@cuda.jit
def cuda_pairs_core(A, B, C, C1, C2, d, base):
    # ...
    if p_i + 1 < A.size and p_j + 1 < A.size:
        i0, i1 = A[p_i], A[p_i + 1]
        j0, j1 = A[p_j], A[p_j + 1]
        cnt = uint64(0)
        for i in range(i0, i1):
            k = uint64(i * max(j0, i))
            k_hi = uint64(k // b_lim)
            k_lo = uint64(k % b_lim)
            for j in range(max(j0, i), j1):
                if k >= low_lim:
                    if C[k_hi] + C1[k_lo // c2_lim] + C2[k_lo % c2_lim] == C[i] + C[j]:
                        cnt += uint64(1)
                k += i
                k_lo += i
                if k_lo >= b_lim:
                    k_lo -= b_lim
                    k_hi += uint64(1)
        cuda.atomic.add(B, (t_i, t_j), cnt)

@njit
def init_c(C, d, BASE):
    p = 1
    for i in range(d):
        for j in range(p - 1, -1, -1):
            for z in range(BASE - 1, -1, -1):
                C[j * BASE + z] = C[j] + (uint64(1) << (z * 4))
        p *= BASE

Попробовал ваш алгоритм на видяшке, работает 4.5 секунды для n=6.

Заодно и осилил n=7

7
2 -> 0.871
156
3 -> 0.002
3399
4 -> 0.002
112025
5 -> 0.018
4505706
6 -> 4.435
213002162
7 -> 974.439

Переписав на С++, на вычисление ушло 25 минут

Лобовой подсчет без каких-либо алгоритмов на видяшке работает 4 секунды! (задача с парами). Если не лень ждать 16 часов сможете узнать ответ для n=7.

7
2 -> 0.675
156
3 -> 0.001
3399
4 -> 0.044
112025
5 -> 4.365
4505706
6 -> 537.973
Hidden text
@cuda.jit(device=True)
def cuda_pair_check(i, j, k, d, base):
    a = cuda.local.array(base, np.uint8)
    for z in range(base):
        a[z] = 0
    for z in range(d):
        a[int(i % base)] += 1
        i = i // base
        a[int(j % base)] += 1
        j = j // base
    for z in range(2*d):
        a[int(k % base)] -= 1
        k = k // base
    nz = 0
    for z in range(base):
        if a[z] == 0:
            nz += 1
    return nz == base


@cuda.jit
def cuda_pairs_core(A, B, d, base):
    assert base == 10
    p_i, p_j = cuda.grid(2)
    t_i, t_j = cuda.threadIdx.x, cuda.threadIdx.y
    low_lim = 1
    for k in range(2*d - 1):
        low_lim *= base
    if p_i + 1 < A.size and p_j + 1 < A.size:
        i0, i1 = A[p_i], A[p_i + 1]
        j0, j1 = A[p_j], A[p_j + 1]
        cnt = uint64(0)
        for i in range(i0, i1):
            i = uint64(i)
            for j in range(j0, j1):
                j = uint64(j)
                if i <= j:
                    k = uint64(i * j)
                    if k < low_lim: continue
                    if cuda_pair_check(i, j, k, d, 10):
                        cnt += 1
        cuda.atomic.add(B, (t_i, t_j), cnt)

def run_cuda_pairs(d):
    num = 2**10
    A = np.linspace(pow(BASE, d - 1), pow(BASE, d), num).astype(np.uint64)
    threads = (2**5, 2**4)
    B = np.zeros(threads, dtype=np.int32)
    blocks = (
            (A.size - 1 + (threads[0] - 1)) // threads[0],
            (A.size - 1 + (threads[1] - 1)) // threads[1],
    )
    A, B = cuda.to_device(A), cuda.to_device(B)
    cuda_pairs_core[blocks, threads](A, B, d, BASE)
    B = B.copy_to_host()
    return np.sum(B)

def main_pairs():
    print(f'start {datetime.datetime.now()}')
    for d in range(2, 8):
        t0 = time.perf_counter()
        cnt = run_cuda_pairs(d)
        t1 = time.perf_counter()
        print(cnt)
        print(f'{d} -> {t1-t0:.3f}')

Ничего не нашлось, а пятнадцать нужно 16 часов ждать. Расширил пространство на несколько порядков, вдруг пригодится потомкам.

Другие основания, из не указанного выше
M=2
(40) 1100111001101110111101000000000100000011 * 1010110100001000010111011110000111010001 = 1000101110000111101110100001000010110101 1100000010000000001011110111011001110011
(42) 111010101010110001000001000101111001101011 * 101100101100110011100110011110011111000101 = 101000111110011110011001110011001101001101 110101100111101000100000100011010101010111

M=3
(18-26) None

M=4
(11) 20221122201 * 33313301202 = 20210331333 10222112202
(12) 220032112122 * 220231112121 = 121211132022 221211230022
(13) 3033122211023 * 2021000003321 = 1233000001202 3201122213303
(19) 3123010113323033123 * 1223000330230123211 = 1123210320330003221 3213303233110103213
(20) 21123300031031323121 * 33203011213013222012 = 21022231031211030233 12132313013000332112
(21) 231122200023011022212 * 200211130021013310311 = 113013310120031112002 212220110320002221132
(21) 131012330133313121331 * 220013120002032330201 = 102033230200021310022 133121313331033210131

M=5
(10) 4402131124 * 1403420431 = 1340243041 4211312044
(10) 4424311302 * 2243042322 = 2232403422 2031134244
(13) 1322024130211 * 4242031404321 = 1234041302424 1120314202231
(15) 204304333140412 * 314110410304121 = 121403014011413 214041333403402
(16-18) None

M=6
(10) 2344420112 * 2433414111 = 1114143342 2110244432
(10) 2230332102 * 3120354411 = 1144530213 2012330322
(10) 1440535111 * 5043054031 = 1304503405 1115350441
(14) 21240011132212 * 42005450351431 = 13415305450024 21223111004212

M=7
(13) 5054030524163 * 5540446553414 = 4143556440455 3614250304505
(14) 26623462035461 * 52046210055512 = 21555001264025 16453026432662

M=8
(10) 6774770256 * 1540253631 = 1363520451 6520774776
(10) 6003775002 * 4000002003 = 3002000004 2005773006
(10) 5470206021 * 7431456225 = 5226541347 1206020745
(13) 6000377750002 * 4000000020003 = 3000200000004 2000577730006

M=9
(7-13) None

M=10
(11-14) None

M=11
(12) 534338726a98 * 598050086292 = 292680050895 89a627833435

M=12
(11) a0a40435495 * 3067a602862 = 268206a7603 59453404a0a
(11) 96124b45043 * 4a8b05766a3 = 3a66750b8a4 34054b42169

M=13
(11) 628ba56c626 * 22a0bc87901 = 10978cb0a22 626c65ab826

M=14
(8-11) None

M=15
(10) 59bcc30787 * e5a4923465 = 5643294a5e 78703ccb95

M=16
(3) 269 * e12 = 21e 962
(6) ab5af2 * 848b85 = 58b848 2fa5ba
(9) 6ebade3a2 * 82b559883 = 388955b28 2a3edabe6

M=17
(2) 6a * c4 = 4c a6
(5) 473d7 * ceg53 = 35gec 7d374
(8) 88b918f2 * 8g554484 = 484455g8 2f819b88
(9) gad3cc3g9 * f8701ac2f = f2ca1078f 9g3cc3dag
(10) None

M=18
(2) 4b * a2 = 2a b4
(5) c060c * 19001 = 10091 c060c
(9) ahb305ahe * 35c8a6702 = 2076a8c53 eha503bha
(9) ad95ea864 * c531fe167 = 761ef135c 468ae59da
(9) a3h94a05h * eh2g90f88 = 88f09g2he h50a49h3a

M=19
(2) 62 * b3 = 3b 26
(3-10) None

M=20
(3) ac5 * j2a = a2j 5ca
(4) ce24 * 4j23 = 32j4 42ec
(5) g040g * 15001 = 10051 g040g
(8) 44ch32i2 * ac2jgh42 = 24hgj2ca 2i23hc44
(9) 4f55610hc * 8bb1h2h02 = 20h2h1bb8 ch01655f4

M=21
(3) 7g7 * ce4 = 4ec 7g7
(7) h41830j * 306fh92 = 29hf603 j03814h

M=22
(6) g5ldhf * 5d5334 = 4335d5 fhdl5g

M=23
(2-8) None

M=24
(5) i060i * 18001 = 10081 i060i
(5) g080g * 1c001 = 100c1 g080g
(5) m823h * ff4de = ed4ff h328m
(5) l7ch3 * h305f = f503h 3hc7l
(5) 6in21 * m4h66 = 66h4m 12ni6
(7) 68kcfj3 * 9jbkbe2 = 2ebkbj9 3jfck86
(8) 62c9lnci * c6f1gm23 = 32mg1f6c icnl9c26
(9) None

@cuda.jit
def cuda_run_core(A, oA, oB, B):
    B0 = B // BASE
    pos = cuda.grid(1)
    if pos + 1 < A.size:
        b_lo = A[pos]
        b_hi = A[pos + 1]
        for b in range(b_lo, b_hi):
            if b % BASE == 0:
                continue
            rb = rev(b)
            a0 = uint64(math.ceil(rb * 1.0 * B / b))
            for a in range(a0, a0 + BASE):
                if not (B0 <= a < B):
                    continue
                ra = rev(a)
                err = uint64(a * b - rb * B)
                if err == ra:
                    oA[pos] = a
                    oB[pos] = b
                if err > B:
                    break

Проверяет все до m=12 за минуту на видюшке. Посмотрим что будет с m=14 через пару часов.

Hidden text
@cuda.jit(device=True)
def cuda_rev(x):
    r = uint64(0)
    while x > 0:
        r = r * BASE + x % BASE
        x = x // BASE
    return uint64(r)


def run_cuda(d):
    # 10 -> 0.638
    # 11 -> 6.601
    # 12 -> 68.787
    # 13 -> 775.907
    num = 2**18
    A = np.linspace(pow(BASE, d - 1), pow(BASE, d), num).astype(np.uint64)
    oA, oB = np.zeros_like(A), np.zeros_like(A)
    threadsperblock = 2**9
    blockspergrid = (A.size - 1 + (threadsperblock - 1)) // threadsperblock
    A, oA, oB = cuda.to_device(A), cuda.to_device(oA), cuda.to_device(oB)
    cuda_run_core[blockspergrid, threadsperblock](A, oA, oB, uint64(pow(BASE, d)))
    A, oA, oB = A.copy_to_host(), oA.copy_to_host(), oB.copy_to_host()
    for x, y in zip(oA, oB):
        if x:
            print(x, '*', y, '=', rev(y), rev(x))


def main():
    for d in range(8, 16):
        t0 = time.perf_counter()
        run_cuda(d)
        t1 = time.perf_counter()
        print(f'{d} -> {t1-t0:.3f}')

вычисления длились 5 часов на 11-ядрах процессора

Чет медленно. Сейчас сделаю побыстрее.

Алгоритм A* — это рекурсивный алгоритм поиска

WTF! В каком это месте он рекурсивный? В целом почти все алгоритмы поиска кратчайшего пути нерекурсивные.

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

Визуализация показала обширное облако обломков после уничтожения советского спутника

Очень сомнительное ограничение в 56 на путь, так-то змейка на карте в 60x60 что-то порядка 1700 дает. В мире плюсов аллокацию из библиотеки можно избежать output iterator-ом, там такое на шаблонах бесплатно, в го так не выйдет.

А где про это можно почитать на русском?

Ого. Ходил еще школьником на его курс по питону 14-15 лет назад, жалко не имел подходящий mindset для этих занятий в то время. Вроде бы делали рисовалку на pygame. Действительно многому научил.

Помню через несколько лет уже в МФТИ сокурсники удивлялись этому факту когда мы учили курс по ОСям по его учебнику.

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

А по сути дела статья какая-то дичь:

Зададим некоторое количество натурально пронумерованных действительных чисел

Какое отношение имеют действительные числа к теории сложности?

Распределение которых может иметь произвольный характер

Ну и зачем нам тут случайные величины? Правда чуть ниже что-то похожее на определение Мартингала.

Если, найдётся такая последовательность, что для неё строго не обнаружиться

Определение классов скопировано правильно, но сразу после этого идет без каких либо пояснений переформулировка на язык последовательностей. Я так и не понял как может быть связана одна последовательность с языком.

оперативно-количественном весе m(WhT) - условно определяется через время за которое с точностью в 100%, без методов аппроксимирования

Фу, ужас, отвратительно.

Ощущение что вы даже свой список литературы не открывали, по первой же ссылке весьма грамотно замечают:

С сожалением приходится констатировать, что проблема эта стала даже слишком популярной. Не будет большим преувеличением сказать, что ферматисты XXI века доказывают, что \mathrm{P}=\mathrm{NP}. Работы с такими "доказательствами" публикуются регулярно и, как правило, несут на себе печать "синдрома непризнанного гения": безудержное самовосхваление, претензии на какие-то выдающиеся открытия, позволяющие одним махом решить все мировые проблемы, и, главное, отсутствие корректных определений и доказательств

Могу посоветовать начать с задач попроще, заодно разберётесь с определениями. Например могу предложить доказать (задача которую студенты получают буквально на втором занятии по ТС) что "для всякого языка из P существует недетерминированная машина Тьюринга разрешающая его за время P". Ну или хотя бы что P лежит в NP.

1
23 ...

Information

Rating
4,334-th
Registered
Activity