как считать количество различий в больших потоках быстро?

Я полагаю, что самое большое преимущество состоит в том, что Вы НЕ связываетесь с конкретным поставщиком. Если Вам не нравится GNU C, можно использовать Лязг, например. Если Вам не нравится Apache, используйте lighttpd или Nginx или язык чероки или... Очень немного частей любого данного технологического стека не позволяют альтернативы.

Оборот не связанный с поставщиком - то, что стандарты, записанные стандарты, существуют для примерно всего. Это - большее преимущество, чем кто-либо прибывающий из "Собственного Мира" может вообразить. Люди пишут документацию с помощью записанных стандартов. Люди пишут код, соответствующий (по крайней мере главным образом) записанным стандартам. Никто не вытягивает ковер из-под Вас, поскольку Крупные Поставщики программного обеспечения склонны делать *cough*BEA*cough*. Проекты, которые отказываются исправлять ошибки, заканчивают тем, что были "разветвлены" и заменены, таким образом, стандарты на самом деле имели тенденцию наблюдаться, а не признаваться на словах *cough*OOXML*cough*.

2
09.07.2013, 03:41
2 ответа

С seekable файлами можно параллелизировать это. Например, Вы могли сделать что-то вроде этого (непротестированное):

# Number of jobs to run at once
jobs=4
# Block size
bs=512
# Total number of block to work with
size=1000000
# Or, to calculate the size automatically for one of the disks,
#size=$(( $(df -B 1 /dev/sda | tail -n1 | awk '{ print $2 }') / $bs ))

# Number of blocks per job
count=$(( $size / $jobs )) 
for i in $(seq 1 $jobs) ; do
    seek=$(( ($i - 1) * $count ))
    cmp -l <(dd bs=$bs skip=$seek count=$count if=/dev/sdb1) <(dd bs=$bs skip=$seek count=$count if=/dev/sdb2) | wc &
done

dd будет только искать однажды когда, если сначала запустится.

2
27.01.2020, 22:01
  • 1
    недостаточно для решения этой проблемы. В первую очередь, текущее решение является слишком медленным фактором 100, и у меня нет 100 центральных процессоров, которые потребовались бы, чтобы приносить вещам до желаемой скорости. Во-вторых, настоящая проблема состоит в том, что вывод туалета-l слишком чрезмерно увеличен в размере и что туалет ищет новые строки и пробел, делая оба плохих удовлетворенными для этой задачи. –  psrandall 09.07.2013, 18:47
  • 2
    Когда его список аргументов -l, Туалет GNU только считает новые строки и байты. То, что в стороне, я пропустил слова, "медленные фактором 100" в Вашем вопросе. Я не знаю ни о каких существующих утилитах, которые могут предусмотреть Ваши потребности. Необходимо будет, вероятно, разработать собственное. –   09.07.2013, 19:30
  • 3
    Спасибо за информацию, что туалет-l не считает слова, следовательно быстрее. –  psrandall 10.07.2013, 03:27
  • 4
    "Медленный фактором 100" неявно в числах, я упомянул (0.2GB/s требуемый, 2MB/s на самом деле поставленный) –  psrandall 10.07.2013, 03:33
  • 5
    , я пропустил это также. Честно говоря, я срочно отправил чтение Вашего вопроса немного. Извините за это. –   10.07.2013, 04:04

Вы не собираетесь получать 1GB/s если Ваша поддержка оборудования это. Самые быстрые жесткие диски на 7 200 об/мин могут достигнуть о 200MB/s со стороны их поверхности, и больше как 100 МБ к 150 МБ по целой поверхности.. Так Ваш, “вероятно, хорошо” число на самом деле выше идеальной фигуры, если у Вас нет необычно быстрых дисков (10krpm, RAID0).

cmp -l | wc может быть ограничен ЦП, потому что Вы спрашиваете wc считать слова, который является немного сложным. cmp -l | wc -l уменьшит нагрузку на ЦП.

Если у Вас нет очень быстрых дисков, cmp -l | wc -l уже, вероятно, IO-bound. При использовании целой дисковой пропускной способности распараллеливание не поможет Вам.

Если cmp -l | wc -l является все еще зависящим от ЦП, или если Вы захотите освободить свой ЦП, чтобы сделать другие вещи, то специальная программа, которая проводит подсчет, будет работать лучше. Предупреждение, непротестированное.

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#define BUFFER_SIZE 1048576
unsigned char buf1[BUFFER_SIZE];
unsigned char buf2[BUFFER_SIZE];
int main (int argc, char *argv[]) {
    FILE *f1, *f2;
    unsigned long long total = 0, diffs = 0;
    unsigned n1, n2, n, i;
    f1 = fopen(argv[1], "r");
    if (f1 == NULL) {perror(argv[1]); return 2;}
    f2 = fopen(argv[2], "r");
    if (f2 == NULL) {perror(argv[2]); return 2;}
    do {
        n1 = fread(buf1, 1, BUFFER_SIZE, f1);
        n2 = fread(buf2, 1, BUFFER_SIZE, f2);
        if (n1 > n2) n = n2; else n = n1;
        for (i = 0; i < n; i++) if (buf1[i] != buf2[i]) ++diffs;
        total += n;
    } while (n1 == BUFFER_SIZE && n2 == BUFFER_SIZE);
    printf("%llu\n", diffs);
    if (ferror(f1)) {perror(argv[1]);}
    if (ferror(f2)) {perror(argv[2]);}
    if (n1 != n2) {
        fprintf(stderr, "Stopped after %llu bytes.\n", total);
        return 1;
    }
    return 0;
}
2
27.01.2020, 22:01
  • 1
    Прекрасный, большое спасибо! Мне нравится он. Сколько времени это брало Вас для записи? Я думал больше об использовании out-of-the-box команды оболочки, но это будет работать точно также. –  psrandall 10.07.2013, 21:32
  • 2
    И да, Вы правы, что 0.2GB/s является максимальной скоростью входящего потока, который является, почему я сказал, что программное обеспечение, работающее на этой скорости, в порядке. Число 1GB/s состояло в том, чтобы только удостовериться, что с любым временным отставанием имеют дело быстро, гарантируя максимальную скорость потоковой передачи. –  psrandall 10.07.2013, 21:37

Теги

Похожие вопросы