Парные мониторы на решающем ударе

Я никогда не пробовал использовать эти специфические технологии RAID, но, по моему опыту, лучше всего работать на уровне файловой системы при попытке переноса данных с одной физической реализации RAID на другую. Что я имею в виду под этим?

Я имею в виду, что я бы получил другой набор дисков и переместил содержимое с 1-го RAID-массива на промежуточное место (некоторый набор жестких дисков, необходимых для его хранения), а затем переконфигурировал бы RAID-накопители в новых технологиях RAID.

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

Использование некоторого пути миграции, несомненно, является менее распространенным подходом, и вы рискуете потерять свои данные в процессе их передачи. Если преобразование провалится каким-либо образом, вы все равно вернетесь к подходу, который я предлагаю.

Итак, я бы откусил пулю и пошёл с этим подходом с самого начала, он просто сработает, и вы потратите гораздо меньше своего драгоценного времени в процессе.

1
23.09.2014, 16:17
1 ответ

Другой подход к объяснению: Когда используется * , оболочка знает, что представляют собой отдельные элементы. Вывод find является только длинным рядом. Оболочка не знает, что такое элементы (и их сепараторы).

Подстановка команд может использоваться в специальном пути с программой, которая выдает выходные данные в кавычках; тогда проблема не появится. Но для того, чтобы сделать оболочку распознавать цитаты вам нужно, например, eval , что часто усложняет все выражение:

eval for var in $(ls --quoting-style=shell)\; do echo '"$var"'\; done
-121--96869-

Мой отклик на мгновение вызова был бы неловким , но если вы обрабатываете много строк - и я говорю о миллионах - вы, вероятно, увидите реальную выгоду от перехода на «реальный» язык программирования.

С учетом этого (и awk , уже взятый в качестве ответа) я написал несколько реализаций на разных языках и провел их тестирование на одном и том же наборе данных 10, 000 строк на твердотельном накопителе PCI-E.

me* (C)                0m1.734s
me (C++)               0m1.991s
me (Python/Pypy)       0m2.390s
me (perl)              0m3.024s
Thor+Glenn (sed|sh)    0m3.353s
me (python)            0m3.359s
jasonwryan+Thor (awk)  0m3.779s
rush (while read)      0m6.011s
Thor (sed)             1m30.947s
me (parallel)          4m9.429s

На первый взгляд Си выглядит лучше, но это была свинья, чтобы бежать так быстро. Pypy и C++ гораздо проще писать и выполнять достаточно хорошо , если вы не говорите о многих миллиардах строк. Если бы это было так, модернизация, чтобы сделать это все в оперативной памяти или на твердотельном накопителе, могло бы быть лучшим вложением, чем улучшение кода.

Очевидно, что за то время, которое я провел, вы, вероятно, могли бы обработать несколько сотен миллионов записей в самый медленный вариант . Если вы можете написать только awk или Bash loops, сделайте это и продолжайте жизнь. Сегодня у меня было слишком много свободного времени.

Я также протестировал некоторые многопоточные опции (в C++ и Python и гибриды с GNU parallel ), но накладные расходы потоков полностью перевешивают любые преимущества для такой простой операции (последовательность расщепление, запись).

Perl

awk ( gawk здесь) будет, честно говоря, моим первым портом вызова для тестирования данных, как это, но вы можете сделать довольно похожие вещи в Perl. Подобный синтаксис, но с немного лучшим дескриптором записи.

perl -ane 'open(my $fh, ">", $F[0].".seq"); print $fh $F[1]; close $fh;' infile

Python

I , как Python. Это мой дневной язык работы, и это просто хороший, прочный и невероятно читаемый язык. Даже новичок мог догадаться, что здесь происходит.

with open("infile", "r") as f:
    for line in f:
        id, chunk = line.split()
        with open(id + ".seq", "w") as fw:
            fw.write(chunk)

Вы должны помнить, что двоичный файл python вашего дистрибутива не является единственной реализацией Python. Когда я проводил этот же тест через Pypy, он был быстрее, чем C без дальнейшей оптимизации логики. Помните об этом, прежде чем писать Python как «медленный язык».

C

Я начал этот пример, чтобы увидеть, что мы действительно можем заставить мой процессор сделать, но, честно говоря, C - это кошмар для кода, если вы не трогали его в течение долгого времени. Это имеет дополнительную обратную сторону, ограничиваясь 100-char линий, хотя это очень просто, чтобы расширить это, я просто не нуждался в этом.

Моя первоначальная версия была медленнее, чем C++ и pypy, но после блога об этом я получил некоторую помощь от Джулиана Клоде .Эта версия сейчас самая быстрая из-за измененных буферов ввода-вывода. Это также много дольше и более вовлечено, чем что-либо другое.

#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <stdlib.h>

#define BUFLEN (8 * 1024)

int main(void) {
    FILE *fp;
    FILE *fpout;

    char line[100];
    char *id;
    char *token;
    char *buf = malloc(BUFLEN);

    fp = fopen("infile", "r");

    setvbuf ( fp , buf , _IOLBF, BUFLEN );
    while (fgets(line, 100, fp) != NULL) {
        id = strtok(line, "\t");
        token = strtok(NULL, "\t");

        char *fnout = malloc(strlen(id)+5);
        fnout = strcat(fnout, id);
        fnout = strcat(fnout, ".seq");

        fpout = fopen(fnout, "w");
        setvbuf ( fpout , NULL , _IONBF , 0 );
        fprintf(fpout, "%s", token);
        fclose(fpout);
    }
    fclose(fp);

    return 0;
}

C++

Хорошо работает и намного легче писать, чем реально C. У вас есть все виды вещей, которые держат вашу руку (особенно когда речь идет о последовательностях и вводе). Все это означает, что вы можете упростить логику. strtok в C является hog, потому что он обрабатывает весь ряд, и тогда нам нужно сделать все, что утомительное выделение памяти. Это просто летит вдоль линии, пока он не попадет на вкладку, и мы вытягиваем сегменты, как мы нуждаемся в них.

#include <fstream>
#include <string>
using namespace std;

int main(void) {
    ifstream in("infile");
    ofstream out;
    string line;

    while(getline(in, line)) {
        string::size_type tab = line.find('\t', 0);
        string filename = line.substr(0, tab) + ".seq";
        out.open(filename.c_str());
        out << line.substr(tab + 1);
        out.close();
    }

    in.close();
}

Параллельный GNU

(не версия morutils). Это хороший лаконичный синтаксис, но OMGSLOW. Возможно, я использую это неправильно.

parallel --colsep '\t' echo {2} \> {1}.seq <infile

Тестовый генератор кабелей

Вот мой генератор данных для 100000 строк [ATGC] * 64. Это не быстро и улучшения очень приветствуются.

cat /dev/urandom | tr -dc 'ATGC' | fold -w 64 | awk 'NR>100000{exit}{printf NR"\t"$0"\n"}' > infile
-121--29618-

Супер + пространство, затем Система, а затем Настройки дисплея для получения дополнительной информации см. http://crunchbang.org/forums/viewtopic.php?id=19797

1
27.01.2020, 23:52

Теги

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