এলোমেলো অঙ্কগুলি সহ 1 গিগাবাইট পাঠ্য ফাইল উত্পন্ন করার দ্রুততম কোনটি?


52

আমি একটি বাশ স্ক্রিপ্ট চেষ্টা করেছি, তবে একটি সাধারণ 1 এমবি ফাইল তৈরি করতে খুব বেশি সময় লেগেছে। আমি মনে করি উত্তরটি ব্যবহারে নিহিত /dev/randomবা /dev/urandom, তবে এখানে অন্যান্য পোস্টগুলি কেবলমাত্র এই জিনিসগুলি ব্যবহার করে কোনও ফাইলে সমস্ত ধরণের ডেটা যুক্ত করার পদ্ধতি দেখায় তবে আমি কেবল সংখ্যা যুক্ত করতে চাই।

সুতরাং, এমন কোনও কমান্ড আছে যা আমি 0 গিগাবাইটের আকারের একটি র‌্যান্ডম ফাইল তৈরি করতে ব্যবহার করতে পারি যেখানে কেবল 0 এবং 9 এর মধ্যে সংখ্যা থাকে?

সম্পাদনা: আমি আউটপুটটি এমন কিছু হতে চাই

0 1 4 7 ..... 9
8 7 5 8 ..... 8
....
....
8 7 5 3 ..... 3

পরিসীমা 0 - 9 যার অর্থ কেবল সংখ্যা 0, 1, 2, 3, 4, 5, 6, 7, 8 এবং 9। এছাড়াও আমার তাদের পৃথক স্থান এবং প্রতি লাইনে 100 হওয়া দরকার n, লাইন সংখ্যা পর্যন্ত। এই এনটি এমন কিছু যা আমি পাত্তা দিই না, আমি চাই আমার চূড়ান্ত আকারটি 1 জিবি হতে হবে।

সম্পাদনা করুন: আমি উবুন্টু 16.04 এলটিএস ব্যবহার করছি



21
আপনার সম্ভবত "এলোমেলো" বলতে যা বোঝানো উচিত - ক্রিপ্টোগ্রাফিক শক্তি এলোমেলো, বা সিউডো-এলোমেলো ক্রম যথেষ্ট?
টবি স্পিড

4
@ পক্সিকিং: নোট করুন যে যদিও আমার উত্তরটি অবশ্যই জিভ-ইন-গাল - আমি আসলে এই জাতীয় কোনও কাজের জন্য কোনও সি প্রোগ্রাম লেখার পরামর্শ দিচ্ছি না! -, আপনি যদি নিয়মিতভাবে এ জাতীয় বিশাল ডেটাসেট তৈরি করেন বা আপনি প্রায়শই এটি উত্সাহিত করেন তবে এই পদ্ধতির ফলে আপনার সময় সাশ্রয় হতে পারে। (আমার ল্যাপটপে এটি প্রায় দশ সেকেন্ডের মধ্যে 1 গিগাবাইট স্পেস-বিভাজিত অঙ্কগুলি জেনারেট করে)) তবে, এটি যদি এক-অফ হয়, তবে এর জন্য কোনও সি প্রোগ্রাম লেখার বিষয়ে চিন্তাও করবেন না (যদি আপনি প্রোগ্রামিং পছন্দ না করেন এবং এটি বিবেচনা না করেন) অনুশীলন বা যেমন); শেল কমান্ড এবং ইউটিলিটিগুলি কম মোট সময় এবং প্রচেষ্টা ব্যয় করে টাস্কটি অর্জন করে।
নামমাত্র প্রাণী

7
এটি বেশ দ্রুত এবং আরএফসি 1149.5 অনুবর্তী:yes 4 | tr '\n' ' ' | fold -w 200 | head -c1G
ম্যাথু

উত্তর:


38

প্রশ্নের শিরোনামের কারণে এটি আংশিকভাবে জিভ-ইন-গাল উত্তর।

আপনি যখন "দ্রুততম উপায় ..." সন্ধান করেন , উত্তরটি প্রায় সবসময়ই কোনও বিশেষ সরঞ্জাম। এই "উত্তরগুলি" তেমন একটি সরঞ্জাম দেখায়, যাতে আপনি পরীক্ষা করতে পারেন।

এটি কোনও গুরুতর উত্তর নয়, কারণ কেবলমাত্র একবার বা খুব কমই করা কাজগুলির জন্য বিশেষায়িত সরঞ্জামগুলির সন্ধান করা উচিত নয়। আপনি দেখুন, আপনি আসলে স্টাফ করার চেয়ে সরঞ্জামগুলি সন্ধান এবং সেগুলি সম্পর্কে আরও বেশি সময় ব্যয় করতে পারেন। শেল এবং ইউটিলিটিগুলি দ্রুত bashএবং awkতা নয় তবে আপনি সাধারণত সেকেন্ড সময় ব্যয় করে কাজটি অর্জন করার জন্য ওয়ান-লাইনার লিখতে পারেন । স্ক্রিপ্টিংয়ের মতো আরও ভাল ভাষাও perlব্যবহার করা যেতে পারে, যদিও এর জন্য শেখার বক্রতা perlখাড়া এবং আমি এ জাতীয় উদ্দেশ্যে এটি সুপারিশ করতে দ্বিধা বোধ করি, কারণ আমি ভয়াবহ পার্ল প্রকল্পগুলির দ্বারা ট্রমাজড হয়েছি। pythonঅন্যদিকে এর চেয়ে ধীর I / O দ্বারা সামান্য প্রতিবন্ধকতা রয়েছে; যদিও আপনি যদি গিগা বাইট ডেটা ফিল্টার বা উত্পন্ন করেন তবে এটি কেবল তখনই সমস্যা।

যে কোনও ক্ষেত্রে, নিম্নলিখিত সি 89 উদাহরণস্বরূপ প্রোগ্রাম (যা কেবলমাত্র উপলব্ধ হলে উচ্চতর নির্ভুলতার ঘড়ির জন্য POSIX.1 ব্যবহার করে) প্রায় 100 এমবি / গুলি প্রজন্মের হার অর্জন করতে হবে (ল্যাপটপে একটি ইনটেল i5-4200U প্রসেসরের সাহায্যে লিনাক্সে পরীক্ষা করা, আউটপুটটি পাইপিং করা থেকে /dev/null), বেশ ভাল সিউডো-এলোমেলো নম্বর জেনারেটর ব্যবহার করে। (আউটপুটটিতে ম্যাট্রিক্সর্যাঙ্ক পরীক্ষা ব্যতীত সমস্ত বিগ ক্রঞ্চ পরীক্ষাগুলি পাস করা উচিত, কারণ কোডটি xorshift64 * এবং অঙ্কগুলি বায়সিং এড়ানোর জন্য বর্জন পদ্ধতি ব্যবহার করে ))

দশমিক-digits.c:

#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <locale.h>
#include <ctype.h>
#include <stdio.h>
#include <errno.h>
#include <time.h>

/* This program is licensed under the CC0 license,
       https://creativecommons.org/publicdomain/zero/1.0/
   In other words, this is dedicated to the public domain.
   There are no warranties either, so if something breaks,
   you only have yourself to blame.
*/

#if _POSIX_C_SOURCE-199309 >= 0
static uint64_t time_seed(void)
{
    struct timespec  ts;

    if (clock_gettime(CLOCK_REALTIME, &ts))
        return (uint64_t)time(NULL);

    return (uint64_t)ts.tv_sec
         ^ (((uint64_t)ts.tv_nsec) << 32);
}
#else
static uint64_t time_seed(void)
{
    return (uint64_t)time(NULL);
}
#endif

/* Preferred output I/O block size.
 * Currently, about 128k blocks yield
 * maximum I/O throughput on most devices.
 * Note that this is a heuristic value,
 * and may be increased in the future.
*/
#ifndef  IO_BLOCK_SIZE
#define  IO_BLOCK_SIZE  262144
#endif

/* This is the Xorshift* pseudo-random number generator.
 * See https://en.wikipedia.org/wiki/Xorshift#xorshift.2A
 * for details. This is an incredibly fast generator that
 * passes all but the MatrixRank test of the BigCrush
 * randomness test suite, with a period of 2^64-1.
 * Note that neither xorshift_state, nor the result of
 * this function, will ever be zero.
*/
static uint64_t xorshift_state;

static uint64_t xorshift_u64(void)
{
    xorshift_state ^= xorshift_state >> 12;
    xorshift_state ^= xorshift_state << 25;
    xorshift_state ^= xorshift_state >> 27;
    return xorshift_state * UINT64_C(2685821657736338717);
}

/* This function returns a number between (inclusive)
 * 0 and 999,999,999,999,999,999 using xorshift_u64()
 * above, using the exclusion method. Thus, there is
 * no bias in the results, and each digit should be
 * uniformly distributed in 0-9.
*/
static uint64_t quintillion(void)
{
    uint64_t result;

    do {
        result = xorshift_u64() & UINT64_C(1152921504606846975);
    } while (!result || result > UINT64_C(1000000000000000000));

    return result - UINT64_C(1);
}

/* This function returns a single uniformly random digit.
*/
static unsigned char digit(void)
{
    static uint64_t       digits_cache = 0;
    static unsigned char  digits_cached = 0;
    unsigned char         retval;

    if (!digits_cached) {
        digits_cache = quintillion();
        digits_cached = 17; /* We steal the first one! */
    } else
        digits_cached--;

    retval = digits_cache % (uint64_t)(10);
    digits_cache /= (uint64_t)(10);

    return retval;
}

static int parse_ulong(const char *src, unsigned long *to)
{
    const char   *end = src;
    unsigned long value;

    if (!src)
        return errno = EINVAL;

    errno = 0;
    value = strtoul(src, (char **)&end, 0);
    if (errno)
        return errno;

    if (end == src)
        return errno = EINVAL;
    while (*end)
        if (isspace(*end))
            end++;
        else
            return errno = EINVAL;

    if (to)
        *to = value;
    return 0;
}

int main(int argc, char *argv[])
{
    unsigned long lines, cols, line, col, seed;

    /* When parsing the command-line parameters,
     * use locale conventions. */
    setlocale(LC_ALL, "");

    /* Standard output should be fully buffered, if possible.
     * This only affects output speed, so we're not too worried
     * if this happens to fail. */
    (void)setvbuf(stdout, NULL, _IOFBF, (size_t)IO_BLOCK_SIZE);

    if (argc < 3 || argc > 4 || !strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")) {
        fprintf(stderr, "\n");
        fprintf(stderr, "Usage: %s [ -h | --help ]\n", argv[0]);
        fprintf(stderr, "       %s COLS LINES [ SEED ]\n", argv[0]);
        fprintf(stderr, "\n");
        fprintf(stderr, "This program generates random decimal digits\n");
        fprintf(stderr, "0 - 9, separated by spaces, COLS per line,\n");
        fprintf(stderr, "LINES lines.  In total, COLS*LINES*2 bytes\n");
        fprintf(stderr, "will be used.\n");
        fprintf(stderr, "\n");
        fprintf(stderr, "SEED is the optional seed for the Xorshift64*\n");
        fprintf(stderr, "pseudo-random number generator used in this program.\n");
        fprintf(stderr, "If omitted, current time is used as the seed.\n");
        fprintf(stderr, "\n");
        return EXIT_SUCCESS;
    }

    if (parse_ulong(argv[1], &cols) || cols < 1UL) {
        fprintf(stderr, "%s: Invalid number of digits per line.\n", argv[1]);
        return EXIT_FAILURE;
    }
    if (parse_ulong(argv[2], &lines) || lines < 1UL) {
        fprintf(stderr, "%s: Invalid number of lines.\n", argv[2]);
        return EXIT_FAILURE;
    }

    if (argc > 3) {
        if (parse_ulong(argv[3], &seed)) {
            fprintf(stderr, "%s: Invalid Xorshift64* seed.\n", argv[3]);
            return EXIT_FAILURE;
        }
    } else
        seed = time_seed();

    /* Since zero seed is invalid, we map it to ~0. */
    xorshift_state = seed;
    if (!xorshift_state)
        xorshift_state = ~(uint64_t)0;

    /* Discard first 1000 values to make the initial values unpredictable. */
    for (col = 0; col < 1000; col++)
        xorshift_u64();

    for (line = 0UL; line < lines; line++) {
        fputc('0' + digit(), stdout);
        for (col = 1UL; col < cols; col++) {
            fputc(' ', stdout);
            fputc('0' + digit(), stdout);
        }
        fputc('\n', stdout);

        /* Check for write errors. */
        if (ferror(stdout))
            return EXIT_FAILURE;
    }

    return EXIT_SUCCESS;
}

আমরা যদি একটি লাইন বাফারে স্যুইচ করি এবং আমরা fwrite()এটি একবারে প্রতিটি অঙ্কের আউটপুট না দিয়ে একবার করে আরও দ্রুত করতে পারি । নোট করুন যে আউটপুট যদি কোনও ব্লক ডিভাইস হয় তবে আংশিক (অ-পাওয়ার-অফ-টু) এড়াতে আমরা স্ট্রিমটি পুরোপুরি বাফার করে রেখেছি।

#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <locale.h>
#include <ctype.h>
#include <stdio.h>
#include <errno.h>
#include <time.h>

#if _POSIX_C_SOURCE-199309 >= 0
static uint64_t time_seed(void)
{
    struct timespec  ts;

    if (clock_gettime(CLOCK_REALTIME, &ts))
        return (uint64_t)time(NULL);

    return (uint64_t)ts.tv_sec
         ^ (((uint64_t)ts.tv_nsec) << 32);
}
#else
static uint64_t time_seed(void)
{
    return (uint64_t)time(NULL);
}
#endif

/* Preferred output I/O block size.
 * Currently, about 128k blocks yield
 * maximum I/O throughput on most devices.
 * Note that this is a heuristic value,
 * and may be increased in the future.
*/
#ifndef  IO_BLOCK_SIZE
#define  IO_BLOCK_SIZE  262144
#endif

/* This is the Xorshift* pseudo-random number generator.
 * See https://en.wikipedia.org/wiki/Xorshift#xorshift.2A
 * for details. This is an incredibly fast generator that
 * passes all but the MatrixRank test of the BigCrush
 * randomness test suite, with a period of 2^64-1.
 * Note that neither xorshift_state, nor the result of
 * this function, will ever be zero.
*/
static uint64_t xorshift_state;

static uint64_t xorshift_u64(void)
{
    xorshift_state ^= xorshift_state >> 12;
    xorshift_state ^= xorshift_state << 25;
    xorshift_state ^= xorshift_state >> 27;
    return xorshift_state * UINT64_C(2685821657736338717);
}

/* This function returns a number between (inclusive)
 * 0 and 999,999,999,999,999,999 using xorshift_u64()
 * above, using the exclusion method. Thus, there is
 * no bias in the results, and each digit should be
 * uniformly distributed in 0-9.
*/
static uint64_t quintillion(void)
{
    uint64_t result;

    do {
        result = xorshift_u64() & UINT64_C(1152921504606846975);
    } while (!result || result > UINT64_C(1000000000000000000));

    return result - UINT64_C(1);
}

/* This function returns a single uniformly random digit.
*/
static unsigned char digit(void)
{
    static uint64_t       digits_cache = 0;
    static unsigned char  digits_cached = 0;
    unsigned char         retval;

    if (!digits_cached) {
        digits_cache = quintillion();
        digits_cached = 17; /* We steal the first one! */
    } else
        digits_cached--;

    retval = digits_cache % (uint64_t)(10);
    digits_cache /= (uint64_t)(10);

    return retval;
}

static int parse_ulong(const char *src, unsigned long *to)
{
    const char   *end = src;
    unsigned long value;

    if (!src)
        return errno = EINVAL;

    errno = 0;
    value = strtoul(src, (char **)&end, 0);
    if (errno)
        return errno;

    if (end == src)
        return errno = EINVAL;
    while (*end)
        if (isspace(*end))
            end++;
        else
            return errno = EINVAL;

    if (to)
        *to = value;
    return 0;
}

int main(int argc, char *argv[])
{
    unsigned long lines, cols, line, col, seed;
    char         *oneline;

    /* When parsing the command-line parameters,
     * use locale conventions. */
    setlocale(LC_ALL, "");

    /* Standard output should be fully buffered, if possible.
     * This only affects output speed, so we're not too worried
     * if this happens to fail. */
    (void)setvbuf(stdout, NULL, _IOFBF, (size_t)IO_BLOCK_SIZE);

    if (argc < 3 || argc > 4 || !strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")) {
        fprintf(stderr, "\n");
        fprintf(stderr, "Usage: %s [ -h | --help ]\n", argv[0]);
        fprintf(stderr, "       %s COLS LINES [ SEED ]\n", argv[0]);
        fprintf(stderr, "\n");
        fprintf(stderr, "This program generates random decimal digits\n");
        fprintf(stderr, "0 - 9, separated by spaces, COLS per line,\n");
        fprintf(stderr, "LINES lines.  In total, COLS*LINES*2 bytes\n");
        fprintf(stderr, "will be used.\n");
        fprintf(stderr, "\n");
        fprintf(stderr, "SEED is the optional seed for the Xorshift64*\n");
        fprintf(stderr, "pseudo-random number generator used in this program.\n");
        fprintf(stderr, "If omitted, current time is used as the seed.\n");
        fprintf(stderr, "\n");
        return EXIT_SUCCESS;
    }

    if (parse_ulong(argv[1], &cols) || cols < 1UL) {
        fprintf(stderr, "%s: Invalid number of digits per line.\n", argv[1]);
        return EXIT_FAILURE;
    }
    if (parse_ulong(argv[2], &lines) || lines < 1UL) {
        fprintf(stderr, "%s: Invalid number of lines.\n", argv[2]);
        return EXIT_FAILURE;
    }

    if (argc > 3) {
        if (parse_ulong(argv[3], &seed)) {
            fprintf(stderr, "%s: Invalid Xorshift64* seed.\n", argv[3]);
            return EXIT_FAILURE;
        }
    } else
        seed = time_seed();

    /* Since zero seed is invalid, we map it to ~0. */
    xorshift_state = seed;
    if (!xorshift_state)
        xorshift_state = ~(uint64_t)0;

    /* Discard first 1000 values to make the initial values unpredictable. */
    for (col = 0; col < 1000; col++)
        xorshift_u64();

    /* Allocate memory for a full line. */
    oneline = malloc((size_t)(2 * cols + 1));
    if (!oneline) {
        fprintf(stderr, "Not enough memory for %lu column buffer.\n", cols);
        return EXIT_FAILURE;
    }

    /* Set spaces and terminating newline. */
    for (col = 0; col < cols; col++)
        oneline[2*col + 1] = ' ';
    oneline[2*cols-1] = '\n';

    /* Not needed, but in case a code modification treats it as a string. */
    oneline[2*cols] = '\0';

    for (line = 0UL; line < lines; line++) {
        for (col = 0UL; col < cols; col++)
            oneline[2*col] = digit();

        if (fwrite(oneline, 2*cols, 1, stdout) != 1)
            return EXIT_FAILURE; 
    }

    /* Check for write errors. */
    if (ferror(stdout))
        return EXIT_FAILURE;

    return EXIT_SUCCESS;
}

দ্রষ্টব্য: ডিজিটের অভিন্ন বন্টন নিশ্চিত করতে 2016-11-18 এ সম্পাদিত দুটি উদাহরণ (শূন্য বাদ দেওয়া হয়েছে; উদাহরণস্বরূপ এখানে বিভিন্ন ছদ্ম-এলোমেলো সংখ্যার জেনারেটরের তুলনা এবং বিশদটি দেখুন)।

উদাহরণস্বরূপ ব্যবহার করে সংকলন করুন

gcc -Wall -O2 decimal-digits.c -o decimal-digits

এবং allyচ্ছিকভাবে /usr/binব্যবহার করতে সিস্টেম-ওয়াইড ইনস্টল করুন

sudo install -o root -g root -m 0755 decimal-digits /usr/bin

এটি প্রতি লাইনে অঙ্কের সংখ্যা এবং রেখার সংখ্যা নেয়। কারণ 1000000000 / 100 / 2 = 5000000(পাঁচ মিলিয়ন; কলাম দ্বারা বিভক্ত মোট বাইট 2 দ্বারা বিভক্ত), আপনি ব্যবহার করতে পারেন

./decimal-digits 100 5000000 > digits.txt

digits.txtওপি কর্তৃক পছন্দসই গিগাবাইট আকারের উত্পাদন করতে ।

নোট করুন যে প্রোগ্রামটি নিজেই দক্ষতার কথা মাথায় রেখে পাঠযোগ্যতার সাথে আরও বেশি লেখা হয়েছে। আমার উদ্দেশ্য এখানে কোডটির দক্ষতা প্রদর্শন করার জন্য নয় - আমি জেনেরিক সি ইন্টারফেসের চেয়ে POSIX.1 এবং নিম্ন-স্তরের I / O ব্যবহার করতাম - তবে আপনি সহজেই দেখতে দিন যে ব্যয় করা প্রচেষ্টা সহ কোন ধরণের ভারসাম্য রয়েছে easily ওয়ান-লাইনার বা শর্ট শেল বা অ্যাজিক স্ক্রিপ্টলেটগুলির তুলনায় তাদের কর্মক্ষমতা বনাম নিবেদিত সরঞ্জামগুলি বিকাশে।

জিএনইউ সি লাইব্রেরি fputc()ব্যবহার করে প্রতিটি চরিত্রের আউটপুটটির জন্য ফাংশনটি কল করা খুব ছোট ওভারহেডকে অন্তর্ভুক্ত করে (একটি পরোক্ষ ফাংশন কল, বা শর্তসাপেক্ষে - FILEইন্টারফেসটি আসলে বেশ জটিল এবং বহুমুখী, আপনি দেখতে পান)। এই নির্দিষ্ট ইন্টেল কোর i5-4200U ল্যাপটপে, আউটপুটটিকে পুনঃনির্দেশিত করে /dev/null, প্রথম (fputc) সংস্করণটি প্রায় 11 সেকেন্ড সময় নেয়, যেখানে লাইন-এ-এ-টাইম সংস্করণটি কেবল 1.3 সেকেন্ড নেয়।

আমি প্রায়শই এই জাতীয় প্রোগ্রাম এবং জেনারেটরগুলি লিখি কেবল কারণ আমি বিশাল ডেটাসেটের সাথে খেলতে চাই। আমি সেভাবে অদ্ভুত। উদাহরণস্বরূপ, আমি একবার একবারে একটি প্রোগ্রাম লিখেছিলাম সমস্ত সীমাবদ্ধ ইতিবাচক আইইইই -754 ভাসমান-পয়েন্ট মান একটি পাঠ্য ফাইলে মুদ্রিত করার জন্য, যথাযথ নির্ভুলতার সাথে পার্স করার সময় যথাযথ মানটি পাওয়া যায়। ফাইলটি কয়েকটি গিগাবাইট আকারের ছিল (সম্ভবত 4 জি বা তাই); কেউ floatমনে করতে পারে না যে অনেক সীমাবদ্ধ ইতিবাচক আছে । আমি এটিকে বাস্তবায়নগুলি তুলনা করতে ব্যবহার করেছি যা এই জাতীয় ডেটা পড়ে এবং পার্স করে।

সাধারণ ব্যবহারের ক্ষেত্রে যেমন ওপি হচ্ছে, শেল স্ক্রিপ্ট এবং স্ক্রিপ্টলেট এবং ওয়ান-লাইনারগুলি আরও ভাল পদ্ধতির। সামগ্রিক কাজ সম্পাদন করতে কম সময় ব্যয় করেছে। (যদি তাদের প্রতিদিন বা অন্য কোনও পৃথক ফাইলের প্রয়োজন হয় তবে, বা এমন অনেক লোক রয়েছে যাদের আলাদা ফাইলের দরকার হয় - এর মধ্যে - বিরল - ক্ষেত্রে, উপরের মতো একটি উত্সর্গীকৃত সরঞ্জাম, ব্যয় করা প্রচেষ্টাটির নিশ্চয়তা দিতে পারে))


হ্যাঁ, সম্ভবত mmap()সেরা I / O গতির সবচেয়ে সহজতম পথ - তবে কোনও দাবি করার আগে বেঞ্চমার্ক!
টবি স্পিড

@ টবিস্পাইট: লিনাক্সে, নিম্ন-স্তরের আই / ও, অর্থাৎ ব্যবহার write()করা সাধারণত তুলনায় দ্রুত হয় mmap()fwrite()খুব ধীর হয় না। হ্যাঁ, আমি এটি বেঞ্চমার্ক করেছি (কেবল এই নির্দিষ্ট উদাহরণের জন্য নয়); write()বড় অংশগুলিতে (262144, 524288, বা 1048576 বাইট) অন্যান্য পদ্ধতিগুলিকে ছাড়িয়ে যায়। fputc()জিএনইউ সি লাইব্রেরিতে বাস্তবায়িত সংস্করণটি (যা আমি আরও ব্যাপকভাবে বেঞ্চমার্ক করেছি) বেশ কয়েকটি কারণে ধীর; বিশেষতঃ শর্তযুক্ত জাম্প বা প্রতিটি চরিত্রের জন্য পরোক্ষ কলগুলি প্রয়োগ করতে হয়; যে সামান্য ওভারহেড ব্যয় প্রায়ই এটি যোগ করে।
নামমাত্র প্রাণী

মাত্র আগ্রহের বাইরে - আপনি অন্যান্য উত্তরের সাথে একটি পারফরম্যান্স তুলনা করেছেন?
ডিজিটাল ট্রমা

2
@ ডিজিটালট্রামা: আউটপুটটিকে পুনর্নির্দেশ করে আমি আপনার জন্য কেবল এগুলি চালিয়েছি /dev/nullস্টাফেন চেজেলাসের স্ক্রিপ্টলেটটি প্রায় 52 সেকেন্ড সময় নেয়; পার্ল স্নিপেট ( headফিল্টারিং সহ ) প্রায় 58 সেকেন্ড; আপনার shufস্নিপেট (সঠিক সময়সীমার সাথে; আপনি কেবলমাত্র শেফ সময় পরিমাপ করেন, অনুমান করে পেস্টটি আর বেশি সময় নেয় না) প্রায় 69 সেকেন্ড সময় লাগে। জেমস হলিসের সি ++ 11 একটি লাইন-এ-এ-টাইম প্রোগ্রামে 14 সেকেন্ড সময় লাগে। উপরের প্রোগ্রামটি 10 ​​সেকেন্ড সময় নেয়।
নামমাত্র প্রাণী

3
(উপরে আমার চিন্তার ট্রেনটি হারিয়েছে, দুঃখিত।) পয়েন্টটি হ'ল সঠিক আলগোরিদমটি বেছে নেওয়া - যথেষ্ট পরিমাণে এলোমেলো তবে খুব দ্রুত পিআরএনজি - - এর গতি বৃদ্ধির প্রায় অর্ডার (10 ×) পেয়েছে। (আমার প্রোগ্রামগুলির পরবর্তী সংস্করণটি শেল বা পার্ল স্নিপেটের চেয়ে প্রায় 40 গুণ বেশি দ্রুত।) এটি সাধারণ ) উপরের আমার উত্তরে আরও একটি প্রোগ্রাম লেখার সময় সম্ভবত আমার সঠিক অ্যালগরিদম বাছাই করার বিষয়ে জোর দেওয়া উচিত ছিল ? (অন্যদিকে, এটি কোনও প্রোগ্রামিং প্রশ্ন নয়, তবে ইউনিক্স / লিনাক্সের প্রশ্ন, কীভাবে প্রচুর অঙ্ক তৈরি করতে হয়))
নামমাত্র এনিমাল

81

এই:

 LC_ALL=C tr '\0-\377' \
             '[0*25][1*25][2*25][3*25][4*25][5*25][6*25][7*25][8*25][9*25][x*]' \
    < /dev/urandom |
    tr -d x |
    fold -w 1 |
    paste -sd "$(printf '%99s\\n')" - |
    head -c1G

(এমন একটি headবাস্তবায়ন যা সমর্থন করে তা ধরে নিলে -c) আমার সিস্টেমে যুক্তিসঙ্গতভাবে দ্রুত বলে মনে হচ্ছে।

trপুরো বাইট পরিসরটি (0 থেকে 255, অক্টালে 0 থেকে 0377) অনুবাদ করে: 25 প্রথম বাইট 0 হিসাবে, 25 পরবর্তীগুলি 1 হিসাবে ... তারপরে 25 9 বাকী (250 থেকে 255) "এক্স" তে যা আমরা তখন বাতিল করুন (সহ tr -d x) আমরা যেমন অভিন্ন বন্টন চাই (ধরে নিই যে অভিন্ন বিতরণ /dev/urandomরয়েছে) এবং তাই কিছু সংখ্যার পক্ষপাতিত্ব না দেয়।

এটি বাইটের 97% এর জন্য একটি অঙ্ক তৈরি করে /dev/urandomfold -w 1প্রতি লাইনে এটিকে এক অঙ্ক করে তোলে। paste -s99 স্পেস অক্ষর এবং একটি নতুনলাইন অক্ষর সমন্বিত বিভাজকের তালিকার সাথে ডাকা হয়, যাতে প্রতিটি লাইনে 100 স্পেস পৃথক অঙ্ক থাকে।

head -c1Gএর মধ্যে প্রথম জিআইবি (2 30 ) পাবে। নোট করুন যে শেষ লাইনটি কেটে ফেলা হবে এবং অপরিমিত করা হবে। আপনি 2 30 -1 এ ছাঁটাই করতে পারেন এবং হাতের সাহায্যে নিখোঁজ নিউলাইন যুক্ত করতে পারেন বা 10 9 বাইটের পরিবর্তে কেটে ফেলতে পারেন যা সেই 200 বাইট লাইনের 50 মিলিয়ন ( head -n 50000000এটি একটি স্ট্যান্ডার্ড / পোর্টেবল কমান্ডও বানাবে)।

এই সময়গুলি ( zshকোয়াড-কোর সিস্টেমে প্রাপ্ত), সিপিইউ সময়টি কোথায় ব্যয় করেছে তার একটি ইঙ্গিত দেয়:

LC_ALL=C tr '\0-\377'  < /dev/urandom  0.61s user 31.28s system 99% cpu 31.904 total
tr -d x  1.00s user 0.27s system 3% cpu 31.903 total
fold -w 1  14.93s user 0.48s system 48% cpu 31.902 total
paste -sd "$(printf '%99s\\n')" -  7.23s user 0.08s system 22% cpu 31.899 total
head -c1G > /dev/null  0.49s user 1.21s system 5% cpu 31.898 total

প্রথমটি trহ'ল বোতল ঘাড়, বেশিরভাগ সময় কর্নালে ব্যয় করা হয়েছে (আমি মনে করি এলোমেলো সংখ্যা জেনারেশনের জন্য)। সময়টি মোটামুটিভাবে আমি যে হার থেকে বাইট পেতে পারি তার সাথে /dev/uramdomসামঞ্জস্যপূর্ণ (প্রায় 19MiB / s এবং এখানে আমরা 32MiB / s এর হারে / dev / urandom এর প্রতি 0.97 বাইটের জন্য 2 বাইট উত্পাদন করি)। foldমনে হচ্ছে প্রতিটি বাইটের পরে একটি নতুন লাইন চরিত্র সন্নিবেশ করানোর জন্য অযৌক্তিক পরিমাণ সিপিইউ সময় (15 সেকেন্ড) ব্যয় করছে তবে এটি সামগ্রিক সময়কে প্রভাবিত করে না কারণ এটি আমার ক্ষেত্রে ভিন্ন সিপিইউতে কাজ করে ( -bবিকল্পটি যুক্ত করা এটি একেবারে আরও সামান্য করে তোলে দক্ষ, dd cbs=1 conv=unblockএকটি ভাল বিকল্প মত বলে মনে হচ্ছে)।

তোমাদেরকে বিলুপ্তিতে নিয়ে যাবেন করতে head -c1Gএবং ফাইল আকার (উপর একটি সীমা সেটিং দ্বারা কয়েক সেকেন্ডের বন্ধ শেভ limit filesize 1024mসঙ্গে zshবা ulimit -f "$((1024*1024))"(তত্সহ অন্যান্য অধিকাংশ শাঁস সঙ্গে zsh)) এর পরিবর্তে একটি subshell হবে।

এটি উন্নত হতে পারে যদি আমরা প্রতিটি বাইটের জন্য 2 ডিজিট বের করি তবে তার জন্য আমাদের আলাদা পদ্ধতির প্রয়োজন হবে। উপরেরটি খুব কার্যকর কারণ trকেবল প্রতিটি বাইট 256 বাইট অ্যারে দেখায় looks এটি একসাথে 2 বাইটের জন্য এটি করতে পারে না এবং এই জাতীয় জিনিসগুলি ব্যবহার hexdump -e '1/1 "%02u"'করে আরও জটিল অ্যালগরিদম ব্যবহার করে বাইটের পাঠ্য উপস্থাপনাকে র্যান্ডম সংখ্যা জেনারেশনের তুলনায় আরও ব্যয়বহুল হতে পারে। তবুও, যদি আমার ক্ষেত্রে পছন্দ হয় তবে আপনার সিপিইউ কোর রয়েছে যার সময়সীমা বেঁধে দেওয়ার জন্য, এটি এখনও কয়েক সেকেন্ড শেভ করতে পারে:

সঙ্গে:

< /dev/urandom LC_ALL=C tr '\0-\377' '\0-\143\0-\143[x*]' |
  tr -d x |
  hexdump -n250000000 -ve '500/1 "%02u" "\n"' |
  fold -w1 |
  paste -sd "$(printf '%99s\\n')" - > /dev/null

আমি পেয়েছি (তবে এখানে লক্ষ্য করুন যে এটি 1,073,741,824 এর বিপরীতে এটি 1,00,000,000 বাইট)

LC_ALL=C tr '\0-\377' '\0-\143\0-\143[x*]' < /dev/urandom  0.32s user 18.83s system 70% cpu 27.001 total
tr -d x  2.17s user 0.09s system 8% cpu 27.000 total
hexdump -n250000000 -ve '500/1 "%02u" "\n"'  26.79s user 0.17s system 99% cpu 27.000 total
fold -w1  14.42s user 0.67s system 55% cpu 27.000 total
paste -sd "$(printf '%99s\\n')" - > /dev/null  8.00s user 0.23s system 30% cpu 26.998 total

সামগ্রিকভাবে আরও সিপিইউ সময়, তবে আমার 4 সিপিইউ কোরের মধ্যে আরও ভাল বিতরণ করা হয়েছে, যাতে এটি কম দেয়াল-ঘড়ির সময় নেয়। বাধা এখন hexdump

আমরা যদি ddলাইন ভিত্তিক পরিবর্তে ব্যবহার করি তবে আমরা foldআসলে কাজের পরিমাণ কমিয়ে hexdumpসিপিইউগুলির মধ্যে কাজের ভারসাম্য উন্নত করতে পারি:

< /dev/urandom LC_ALL=C tr '\0-\377' '\0-\143\0-\143[x*]' |
  tr -d x |
  hexdump -ve '"%02u"' |
  dd bs=50000 count=10000 iflag=fullblock status=none cbs=1 conv=unblock |
  paste -sd "$(printf '%99s\\n')" -

(এখানে এর ddজন্য জিএনইউ ধরে নেওয়া iflag=fullblockএবং status=none) যা দেয়:

LC_ALL=C tr '\0-\377' '\0-\143\0-\143[x*]' < /dev/urandom  0.32s user 15.58s system 99% cpu 15.915 total
tr -d x  1.62s user 0.16s system 11% cpu 15.914 total
hexdump -ve '"%02u"'  10.90s user 0.32s system 70% cpu 15.911 total
dd bs=50000 count=10000 iflag=fullblock status=none cbs=1 conv=unblock  5.44s user 0.19s system 35% cpu 15.909 total
paste -sd "$(printf '%99s\\n')" - > /dev/null  5.50s user 0.30s system 36% cpu 15.905 total

এলোমেলো নম্বর প্রজন্মের পিছনে ফিরে আসা।

এখন, @ ওলেট্যাঞ্জের নির্দেশ অনুসারে, আপনার যদি opensslইউটিলিটি থাকে তবে আপনি এটি দ্রুত (বিশেষত এইএস নির্দেশাবলী প্রসেসরের ক্ষেত্রে) বাইটগুলির সিউডো-র্যান্ডম জেনারেটর পেতে ব্যবহার করতে পারেন।

</dev/zero openssl enc -aes-128-ctr -nosalt -pass file:/dev/urandom

আমার সিস্টেমে প্রতি সেকেন্ডের চেয়ে 15 গুণ বেশি বাইট রয়েছে /dev/urandom। (এটি যদি আপনার ব্যবহারের ক্ষেত্রে প্রযোজ্য হয় তবে এলোমেলোভাবে সুরক্ষিত সুরক্ষার উত্সের সাথে এটি কীভাবে তুলনা করা যায় সে বিষয়ে আমি মন্তব্য করতে পারি না )।

</dev/zero openssl enc -aes-128-ctr -nosalt -pass file:/dev/urandom 2> /dev/null | 
  LC_ALL=C tr '\0-\377' '\0-\143\0-\143[x*]' |
  tr -d x |
  hexdump -ve '"%02u"' |
  dd bs=50000 count=10000 iflag=fullblock status=none cbs=1 conv=unblock |
  paste -sd "$(printf '%99s\\n')" -

এখন দেয়:

openssl enc -aes-128-ctr -nosalt -pass file:/dev/urandom < /dev/zero 2>   1.13s user 0.16s system 12% cpu 10.174 total
LC_ALL=C tr '\0-\377' '\0-\143\0-\143[x*]'  0.56s user 0.20s system 7% cpu 10.173 total
tr -d x  2.50s user 0.10s system 25% cpu 10.172 total
hexdump -ve '"%02u"'  9.96s user 0.19s system 99% cpu 10.172 total
dd bs=50000 count=10000 iflag=fullblock status=none cbs=1 conv=unblock  4.38s user 0.20s system 45% cpu 10.171 total
paste -sd "$(printf '%99s\\n')" - > /dev/null

ফিরে hexdumpআসা বাধা।

যেহেতু আমার এখনও সিপিইউ ছাড়ার মতো নেই, আমি তাদের hexdumpসমান্তরাল 3 টি চালাতে পারি ।

</dev/zero openssl enc -aes-128-ctr -nosalt -pass file:/dev/urandom 2> /dev/null | 
  LC_ALL=C tr '\0-\377' '\0-\143\0-\143[x*]' |
  tr -d x |
  (hexdump -ve '"%02u"' <&3 & hexdump -ve '"%02u"' <&3 & hexdump -ve '"%02u"') 3<&0 |
  dd bs=50000 count=10000 iflag=fullblock status=none cbs=1 conv=unblock |
  paste -sd "$(printf '%99s\\n')" -

( পটভূমিতে চলাকালীন ঘনিষ্ঠ কমান্ডগুলির স্টিডিন অন / ডিভ / নাল <&3ব্যতীত শেলগুলির জন্য প্রয়োজনীয় zsh)

এখন 6.২ সেকেন্ডের নিচে এবং আমার সিপিইউগুলি প্রায় সম্পূর্ণরূপে ব্যবহৃত হয়েছে।


3
আমি স্রেফ আমার পূর্ববর্তী উত্তরটি মুছে ফেলেছি এবং এইটির জন্য ভোট দিয়েছি। আমি কিছু প্রয়োজনীয়তা পেলাম না। সুন্দর উত্তর বিটিডব্লিউ।
মার্সেলো

3
কেন আপনি প্রতিটি পাসে একাধিক সংখ্যা তৈরি করেন না? এমনকি আপনি যদি বাইট-বাই-
বাইতে

@ ল্যুভেনফ্যাক, আমি perlরূপটি সরিয়েছি যা যাইহোক উল্লেখযোগ্যভাবে ধীর ছিল। আমি সেই টিআর | ভাঁজ | পেস্ট পদ্ধতির সাথে বাইট প্রতি 2 সংখ্যা পেতে পারি না।
স্টাফেন চেজেলাস

আমি আফকের বা আমি নিজেই এটি চেষ্টা করে দেখছি, তবে আপনি একবারে ৪২ বাইটকে ১০০-১০২ অঙ্কে রূপান্তর করতে চেষ্টা করে ব্যবহার করতে পারেন bc(তারপরে ০, ১, বা ২ টি সর্বাধিক উল্লেখযোগ্য সংখ্যা হ্রাস করুন)।
এরিক টাওয়ার

gitlab.com/ole.tange/tangetools/tree/master/rand প্রতি সেকেন্ডে 1-4 জিবি সিউডোরেন্ডম উত্পন্ন করে (এইএস গুণমান)।
ওলে টাঞ্জ

23

আপনার যদি shufউপলভ্য থাকে (সাম্প্রতিক জিএনইউ কোর্টিলগুলি করেন) আপনি এটি করতে পারেন:

time shuf -r -n $((512*1024*1024)) -i 0-9 | paste -sd "$(printf '%99s\\n')" -

আমার ভিএম-তে, স্টাফেনের উত্তরটির তুলনায় এটি এখন প্রায় 3: 4 ফ্যাক্টরের চেয়ে কিছুটা ধীর।


shufউপর আমার কোম্পানির পিসি নেই -r, fmtনেই -gখুব
phuclv

2
@ LưuVĩnhPhúc ইয়েপ - ওয়াইএমএমভি। আমি কোর-ইউটিস সংস্করণটি 8.25 এ পেয়েছি তবে 8.4 রয়েছে না। আপনি কি সংস্করণ ব্যবহার করছেন?
ডিজিটাল ট্রমা


@ স্টাফেনচেজেলাস চালাক paste/ printfট্রিক - ধন্যবাদ আপনার উত্তর এখন স্পষ্টতই দ্রুত।
ডিজিটাল ট্রমা

17

আপনি খুব উচ্চ মানের যদৃচ্ছতা প্রয়োজন না থাকে, তাহলে এবং বন্ধ-টু-সমবন্টন যথেষ্ট ভাল, আপনি যেতে পারেন সত্যিই দ্রুত, বিশেষত SSE2 বা AVX2 সঙ্গে এক্স 86 মত দক্ষ SIMD পূর্ণসংখ্যা ভেক্টর একটি আধুনিক CPU তে।

এটি @ নোমিনালঅ্যানিমালের উত্তরের মত, যেহেতু আমাদের দুজনেরই একই ধারণা ছিল তবে x86 এর জন্য ম্যানুয়ালি ভেক্টরাইজড। (এবং আরও খারাপ মানের এলোমেলো সংখ্যার সাথে, তবে এখনও প্রচুর ব্যবহারের ক্ষেত্রে এটি যথেষ্ট ভাল)) এটি 2.5 ন্যূনগা হার্জ ইনটেল হ্যাসওয়েলে ASCII আউটপুটটির N 13 গিগাবাইট / এস-এ নোমিনালের কোডের চেয়ে প্রায় 15 বা 30 গুণ বেশি দ্রুত গতিতে চলেছে This এভিএক্স 2 সহ সিপিইউ। এটি তাত্ত্বিক সর্বোচ্চ প্রধান মেমরি মেমরি ব্যান্ডউইদথের চেয়ে কম (দ্বৈত চ্যানেল ডিডিআর ৩3-১00০০ প্রায় ২৫.GB গিগাবাইট / সে) তবে আমি / দেব / নালকে লেখার সময় দিচ্ছিলাম যাতে এটি কেবল ক্যাশে গরম থাকে এমন একটি বাফার পুনরায় লেখার জন্য। স্কাইলেকের এই একই কোডটি হাসওয়ালের তুলনায় উল্লেখযোগ্যভাবে দ্রুত চালানো উচিত (এই উত্তরটির নীচে দেখুন)।

ধরে নিই যে আপনি আসলে আই / ও-তে ডিস্কে বাধা দিচ্ছেন বা এটিকে কোথাও পাইপ দিচ্ছেন, দ্রুত প্রয়োগের অর্থ আপনার সিপিইউ এমনকি নিষ্ক্রিয়ের চেয়ে বেশি ঘড়িও নিতে হবে না। ফলাফলটি তৈরি করতে এটি মোট কম শক্তি ব্যবহার করে। (ব্যাটারির জীবন / তাপ / গ্লোবাল ওয়ার্মিং।

এটি এত দ্রুত যে আপনি সম্ভবত এটি ডিস্কে লিখতে চান না। কেবল প্রয়োজন অনুসারে পুনরায় জেনারেট করুন (যদি আপনি আবার একই ডেটা চান তবে একই বীজ থেকে)। এমনকি আপনি যদি এটি কোনও বহু-থ্রেড প্রক্রিয়াতে ফিড করতে চান যা সমস্ত সিপিইউ ব্যবহার করতে পারে তবে ডেটা এটিতে পাইপ করার জন্য এটি চালানো L3 ক্যাশে গরম থাকবে (এবং এটিতে লেখা L2 ক্যাশে যেটি লিখেছিল) এবং খুব ব্যবহার করুন সামান্য সিপিইউ সময়। (তবে নোট করুন যে /dev/nullপাইপিংয়ের ফলে বনাম প্রচুর ওভারহেড যুক্ত হয়েছে Sk একটি স্কাইলেক আই --kk০০ কে-তে পাইপিং wc -cবা অন্য কোনও প্রোগ্রাম যা কেবল পড়ে + এটির ইনপুট বাতিল করে দেয়, এটি লেখার চেয়ে প্রায় ৮ গতি কম/dev/null এবং কেবলমাত্র a০ % ব্যবহার করে সিপিইউ।কিন্তু এটি এখনও 3.9 গিগাহার্টজ সিপিইউতে 4.0 জিবি / এস।

এটি একটি দ্রুত পিসিআই-সংযুক্ত এসএসডি থেকে পুনরায় পড়ার চেয়ে দ্রুততর, তবে IDK যদি এটি আরও বেশি দক্ষ দক্ষ হয় (ভেক্টর-ইন্টিজার গুণকটি বেশ ব্যস্ত রাখা হয়, এবং এটি সম্ভবত অন্যান্য এভিএক্স 2 সহ বেশ শক্তিশালী-ক্ষুধার্ত হয়) 256 বি ভেক্টর এএলইউ)। ওও, আমি জানি না যে ডিস্ক থেকে পড়া সিপিইউ সময় এমন কিছু থেকে সরিয়ে ফেলবে যা এই ইনপুটটির প্রক্রিয়াকরণে সমস্ত কোরকে সর্বাধিক প্রসারিত করছে। আমি অনুমান করেছিলাম যে 128k অংশগুলিতে পুনরায় জেনারেট করার জন্য একটি প্রসঙ্গ-স্যুইচ ফাইল সিস্টেম / পেজক্যাচ কোড চালানো এবং ডিস্ক থেকে ডেটা পড়তে পৃষ্ঠাগুলি বরাদ্দের সাথে প্রতিযোগিতামূলক হতে পারে। অবশ্যই, যদি এটি ইতিমধ্যে পেজকেচে গরম থাকে তবে এটি মূলত মেমসিপি। ওও, আমরা ইতিমধ্যে ম্যাকপি হিসাবে দ্রুত সম্পর্কে লিখি! (যা পড়ার এবং লেখার মধ্যে প্রধান মেমরি ব্যান্ডউইথকে বিভক্ত করতে পারে)। (স্মরণে রাখুন যে লেখাটি নোট করুন 'rep movsb(মাইক্রোকোডে অপ্টিমাইজড মেমকি এবং মেমসেট, যা আরএফওকে এড়িয়ে চলে, যেহেতু অ্যান্ডি গ্লিউ এর পি 6 (পেন্টিয়াম প্রো) ) এ প্রয়োগ করেছে )।


এখনও অবধি এটি কেবল ধারণার প্রমাণ এবং নতুন লাইন হ্যান্ডলিংটি কেবল প্রায় সঠিক। পাওয়ার-অফ -২ বাফারের প্রান্তের চারপাশে এটি ভুল। আরও উন্নয়নের সময় সহ। আমি নিশ্চিত যে আমি নিউলাইনগুলি সুনির্দিষ্টভাবে সঠিকভাবে সন্নিবেশ করানোর আরও কার্যকর উপায় খুঁজে পেতে পারি, ওভারহেড কমপক্ষে এটির চেয়ে কম হিসাবে (কেবলমাত্র ফাঁকা স্থানের তুলনায়)। আমি মনে করি এটি 10 ​​থেকে 20% এর মতো। আমি কেবল এই রানটি কীভাবে তৈরি করতে পেরেছি তা জানতে আগ্রহী, আসলে এটির কোনও পালিশ সংস্করণ নেই, তাই আমি সেই অংশটি পাঠকের জন্য অনুশীলন হিসাবে ছেড়ে দেব, মন্তব্যগুলিতে কিছু ধারণার বর্ণনা দিয়ে।


একটি হাইওয়েল আই 5 এর 2.5GHz সর্বোচ্চ টার্বোতে , DDR3-1600MHz র‌্যাম সহ সময়সীমার 100GiB উত্পাদন করে তবে নিচে মজুত হয়। (জিসিসি ৫.৪ সহ উইন ১০-এ সাইগউইন 64৪ এর সময়সীমা -O3 -march=nativeবাদ দেওয়া -funroll-loopsহয়েছে , যেহেতু এই ধার করা ল্যাপটপটিতে শালীন সময় চালানোর জন্য আমার যথেষ্ট সময় ব্যয় হচ্ছিল on ইউএসবিতে কেবল লিনাক্স বুট করা উচিত ছিল)।

অন্যথায় সুনির্দিষ্ট না করাতে / dev / নালকে লেখা।

  • জেমস হলিস এর: (পরীক্ষিত নয়)
  • নামমালার লেখার সংস্করণ: ~ 2.21
  • এটি (এসএসই 2): ~ 0.142s (আনসাইক্লড টাইমস = রিয়েল = 14.232 এস, ইউজার = 13.999 এস, সিএস = 0.187)।
  • এটি (AVX-128): ~ 0.140s
  • এটি (এভিএক্স 2): ~ 0.073 এস (আনস্কেলড: রিয়েল = 0 এম 7.291 এস, ইউজার = 0 এম 7.125 সে, সিএস = 0 এম0.155 এস)।
  • এটিতে (এভিএক্স 2) সাইগউইন পাইপ করছে wc -c, 128kiB বাফার আকারের সাথে: 0.32s সিপিইউ সহ 2.38GHz (সর্বোচ্চ ডুয়াল-কোর টার্বো)। (অনাবৃত সময়: আসল = 32.466 এর ব্যবহারকারী = 11.468 এস সিএস = 41.092, এটি এবং উভয়ই সহ wc)। যদিও কেবলমাত্র অর্ধেক ডেটা অনুলিপি করা হয়েছিল, কারণ আমার নির্বোধ প্রোগ্রামটি ধরে নিয়েছে যে লেখাই পুরো বাফার করে, যদিও এটি ঘটনাটি নয় এবং সাইগউইন () কেবল পাইপে কল করে call৪ কে করে।

সুতরাং এসএসই 2 এর সাথে এটি @ নামমাল অ্যানিমাল এর স্কেলার কোডের চেয়ে 15 গুণ বেশি গতিযুক্ত। এভিএক্স 2 সহ এটি প্রায় 30 গুণ বেশি দ্রুত। আমি নমিনালের কোডটির কোনও সংস্করণ চেষ্টা করিনি যা কেবলমাত্র write()পরিবর্তে ব্যবহার করে fwrite(), তবে সম্ভবত বড় বাফারদের জন্য স্টডিও বেশিরভাগ ক্ষেত্রেই বাইরে থাকে। যদি এটি ডেটা অনুলিপি করে থাকে তবে এতে প্রচুর মন্দা পড়বে।


টাইমস একটি কোর 2 ডুও ই 6600 (মেরোম 2.4GHz, 32kiB প্রাইভেট এল 1, 4 এমআইবি শেয়ারকৃত এল 2 ক্যাশে), ডিডিআর 2-533 এমএইচজেডে 64 বিট লিনাক্স 4.2 (উবুন্টু 15.10) তে 1 জিবি ডেটা উত্পাদন করবে । এখনও লেখার জন্য একটি 128kiB বাফার আকার ব্যবহার করে (), সেই মাত্রাটি অন্বেষণ করেনি।

অন্যথায় সুনির্দিষ্ট না করাতে / dev / নালকে লেখা।

  • (এসএসই ২) এটিকে নিউলাইন হ্যান্ডলিং এবং এলোমেলো বাইটগুলির প্রতিটি ভেক্টর থেকে 4 টি সংখ্যার ভেক্টর সহ: 0.183s (18.3s এ 100GiB করার সময়সই হয়েছে, তবে 1GiB রানের জন্য অনুরূপ ফলাফল)। চক্র প্রতি 1.85 নির্দেশাবলী।
  • (এসএসই 2) এটিতে পাইপ করুন wc -c: 0.593 এস (আনসিল্ডড: রিয়েল = 59.266 এস ইউজার = 20.148 এস সিএস = 1 এম 6.548 এস, ডাব্লিউসি এর সিপিইউ সময় সহ)। সাইগউইনের মতো একই সংখ্যক রাইটিং () সিস্টেম কল করে তবে আসলে সমস্ত ডেটা পাইপ করা হয় কারণ লিনাক্স একটি পাইপে সমস্ত 128k রাইটিং () র পরিচালনা করে।
  • নোমিনালঅ্যানিমালের fwrite()সংস্করণ (gcc5.2 -O3 -march=native), ./decdig 100 $((1024*1024*1024/200)) > /dev/nullপ্রতি চক্রের 1.40 নির্দেশ সহ : 3.19s +/- 0.1% দিয়ে চালিত । -ফুনরোল-লুপগুলি সম্ভবত একটি ছোট পার্থক্য করেছে। clang-3.8 -O3 -march=native: 3.42 এস +/- 0.1%
  • নামমাত্র- এতে fwriteপাইপিং করা হচ্ছে wc -c: আসল = 3.980 এর ব্যবহারকারী = 3.176 এস সিএস = 2.080 এস
  • জেমস হোলিস-এর-সময়ে-সময়ে-সংস্করণ ( clang++-3.8 -O3 -march=native): 22.885 এস +/- 0.07%, প্রতি চক্রের 0.84 নির্দেশাবলীর সাথে। (g ++ 5.2 সামান্য ধীর ছিল: 22.98 সে)। একবারে কেবল একটি পংক্তি লেখা সম্ভবত উল্লেখযোগ্যভাবে আঘাত করেছে।
  • স্টাফেন tr < /dev/urandom | ...চ্যাজেলাসের: আসল = 41.430 সে ব্যবহারকারী = 26.832 এস সিএস = 40.120 এস। trবেশিরভাগ সময় নিজের কাছে সিপিইউ কোর পেয়ে যাচ্ছিল, প্রায় সমস্ত সময় কার্নেল ড্রাইভারের মধ্যে এলোমেলো বাইট তৈরি করে এবং একটি পাইপে অনুলিপি করে ব্যয় করে। এই ডুয়াল কোর মেশিনের অন্যান্য কোরটি বাকী পাইপলাইনটি চালাচ্ছিল।
  • time LC_ALL=C head -c512M </dev/urandom >/dev/null: অর্থাত কেবল পাইপিংয়ের সাথে এতটা এলোমেলোভাবে পড়া: বাস্তব = 35.018 এর ব্যবহারকারী = 0.036 এস সিএস = 34.940 এস।
  • লু ভান ফ্যাকের পার্ল প্রোগ্রাম (উবুন্টু 15.10 থেকে পার্ল ভি 5.20.2)
    LANG=en_CA.UTF-8: রিয়েল = 4 এম 32.634 এস ব্যবহারকারী = 4 এম 3.288 এস সিএস = 0 এম 29.364।
    LC_ALL=C LANG=C: আসল = 4m18.637s ব্যবহারকারী = 3m50.324 sys = 0m29.356s। এখনও খুব ধীর।

  • (এসএসই 2) এটি কোনও নিউলাইন হ্যান্ডলিং ছাড়াই , এবং এলোমেলো বাইটগুলির প্রতিটি ভেক্টর থেকে 3 বা 4 সংখ্যক ভেক্টর (প্রায় ঠিক একই গতি: dig3 = v%10পদক্ষেপটি এই এইচডাব্লুয়ের বিরতি-এমনকি প্রায়): 0.166 (প্রতিটি চক্র প্রতি 1.82 নির্দেশ) । নিখুঁতভাবে দক্ষ নিউলাইন হ্যান্ডলিংয়ের সাথে আমরা কী কাছে আসতে পারি তার মূলত এটি নিম্ন সীমা।

  • (SSE2) কোন সম্পর্কে newline হ্যান্ডলিং সঙ্গে এই পুরোনো সংস্করণ, কিন্তু শুধুমাত্র ব্যবহার uint16_t উপাদান প্রতি এক অঙ্ক পেয়ে v%10, 0,222 সেকেন্ড +/- 0.4%, চক্র প্রতি 2.12 নির্দেশাবলী। (Gcc5.2, দিয়ে সংকলিত -march=native -O3 -funroll-loops। এই হার্ডওয়্যারটিতে এই কোডটির জন্য আনলোল লুপগুলি ঘটবে। এটি অন্ধভাবে ব্যবহার করবেন না, বিশেষত বড় প্রোগ্রামগুলির জন্য)।
  • (এসএসই 2) এর পুরানো সংস্করণ, কোনও ফাইলকে লিখিত (3 দ্রুত চৌম্বকীয় হার্ড ড্রাইভের একটি RAID10f2 এ, লেখার জন্য খুব অনুকূল নয়): ~ 4 সেকেন্ড। লেখার আগে () ব্লক করার আগে অনেক বেশি নোংরা ডেটা মঞ্জুর করার জন্য কার্নেল I / O বাফার সেটিংস টুইট করে দ্রুত যেতে পারে। "সিস্টেম" সময় এখনও "ব্যবহারকারী" সময়ের চেয়ে অনেক বেশি ~ 1.0 সেকেন্ড than ধীরে ধীরে DDR2-533 র‌্যাম সহ এই পুরানো সিস্টেমে, কার্নেলটি পৃষ্ঠার ক্যাশে ডেটা ম্যাকপি করতে এবং এক্সএফএস ফাংশন চালাতে ~ 4x আর বেশি সময় নেয় এটি আমার লুপের জন্য গরম জায়গায় থাকে এমন একটি বাফারে পুনরায় লেখার জায়গায় রাখে does ক্যাশে।

কিভাবে এটা হলো

একটি দ্রুত পিআরএনজি স্পষ্টতই অপরিহার্য। xorshift128 + ভেক্টরাইজ করা যেতে পারে, তাই আপনার কাছে সিমড ভেক্টরের উপাদানগুলিতে সমান্তরালে দুটি বা চার 64-বিট জেনারেটর রয়েছে। প্রতিটি পদক্ষেপ এলোমেলো বাইটের একটি সম্পূর্ণ ভেক্টর উত্পাদন করে। ( 256 বি এভিএক্স 2 বাস্তবায়ন এখানে ইন্টেল অভ্যন্তরীণ সাথে )। আমি নামমিনালের পছন্দের xorshift * এর উপরে এটি বেছে নিয়েছি, কারণ -৪-বিট ভেক্টর পূর্ণসংখ্যার গুণ কেবল এসএসই 2 / এভিএক্স 2 এ বর্ধিত-নির্ভুলতার কৌশলগুলির সাহায্যে সম্ভব


এলোমেলো বাইটের ভেক্টর দেওয়া, আমরা প্রতিটি 16-বিট উপাদান একাধিক দশমিক অঙ্কে কাটাতে পারি। আমরা 16-বিট উপাদানগুলির একাধিক ভেক্টর উত্পাদন করি যা প্রতিটি ASCII ডিজিট + ASCII স্পেস । আমরা এটি সরাসরি আমাদের আউটপুট বাফারে সংরক্ষণ করি।

আমার আসল সংস্করণটি কেবল x / 6554কোনও ভেক্টরের প্রতিটি uint16_t উপাদান থেকে একটি এলোমেলো অঙ্ক পেতে ব্যবহৃত হয়েছিল। এটি সর্বদা 0 এবং 9 এর মধ্যে থাকে lusive এটি পক্ষপাতদুষ্ট দূরে 9, কারণ (2^16 -1 ) / 6554এটি শুধুমাত্র 9.99923 is (6554 = সিল ((2 ^ 16-1) / 10)) যা নিশ্চিত করে যে ভাগফল সবসময় <10)

x/6554একটি "যাদু" ধ্রুবক ( স্থির-পয়েন্ট পারস্পরিক ) এবং উচ্চ-অর্ধ ফলাফলের ডান শিফট দ্বারা এক গুণে গুণ করা যায় । এটি একটি ধ্রুবক দ্বারা বিভাগের জন্য সেরা কেস; কিছু বিভাজনকারী আরও ক্রিয়াকলাপ গ্রহণ করে এবং স্বাক্ষরিত বিভাগে অতিরিক্ত কাজ লাগে। x % 10একটি অনুরূপ পক্ষপাত আছে এবং গণনা করা হিসাবে সস্তা নয়। (জিসিসির এসএম আউটপুট সমতুল্য x - 10*(x/10), যেমন একটি অতিরিক্ত গুণক এবং একটি মডুলার গুণক বিপরীত ব্যবহার করে বিভাগের শীর্ষে বিয়োগ করা হবে)) এছাড়াও, xorshift128 + এর সর্বনিম্ন বিটটি উচ্চ মানের নয় , তাই উচ্চ বিট থেকে এনট্রপি নিতে ভাগ করা ভাল ( কম বিট থেকে এন্ট্রপি নেওয়ার জন্য মডুলোর চেয়ে মানের পাশাপাশি গতির জন্য)।

তবে আমরা @ নোমিনালের digit()ফাংশনের মতো স্বল্প দশমিক সংখ্যা দেখে প্রতিটি uint16_t এ আরও বেশি এনট্রপি ব্যবহার করতে পারি । সর্বোচ্চ পারফরম্যান্সের জন্য, আমি কম 3 দশমিক সংখ্যা নেওয়ার সিদ্ধান্ত নিয়েছি এবং x/6554একটি পিএমএলএলডাব্লু এবং পিএসইউবিডু (এবং সম্ভবত কিছু এমওভিডিকিএ) বনাম 4 টি কম দশমিক সংখ্যার উচ্চ মানের মানের বিকল্পটি সংরক্ষণ করতে চাই। এক্স / 6554 নিম্ন 3 দশমিক সংখ্যা দ্বারা সামান্য প্রভাবিত হয়, সুতরাং একই উপাদান থেকে অঙ্কগুলির মধ্যে কিছু পারস্পরিক সম্পর্ক রয়েছে (ভেক্টরের প্রস্থের উপর নির্ভর করে ASCII আউটপুটে 8 বা 16 অঙ্কের বিভাজন)।

আমি মনে করি জিসিসিটি একটি দীর্ঘ চেইনের পরিবর্তে ১০ দ্বারা এবং এক দ্বারা 1000 দ্বারা বিভক্ত হয়ে গেছে, সুতরাং এটি সম্ভবত নন-লুপ বহনকারী নির্ভরতা শৃঙ্খলার দৈর্ঘ্যটি ছোট করে না যা প্রতিটি পিআরএনজি আউটপুট থেকে 4 টি ফলাফল দেয় produces পোর্ট0 (ভেক্টর মাল্টিপল এবং শিফট) হ'ল মডুলার গুণিত বিপরীত কারণ, এবং জোরশিফ্ট + এ পরিবর্তনগুলি কারণ এটি একটি ভেক্টর-গুণকে বাঁচাতে অবশ্যই কার্যকর।

xorshift + এত দ্রুত যে এমনকি প্রতি 16 টি (অর্থাৎ 20% দক্ষতা) থেকে কেবল only 3.3 বিট ব্যবহার করে এটিকে একাধিক দশমিক সংখ্যায় কাটানোর চেয়ে খুব ধীর নয়। আমরা কেবল ইউনিফর্ম বিতরণ আনুমানিক, কারণ গুণমান খুব খারাপ না হওয়া পর্যন্ত এই উত্তরটি গতির দিকে নিবদ্ধ থাকে isn't

যে কোনও ধরণের শর্তাধীন আচরণ যা ভেরিয়েবল সংখ্যক উপাদানকে রাখে আরও বেশি কাজ করতে পারে। (তবে সম্ভবত সিমড বাম-প্যাকিং কৌশলগুলি ব্যবহার করে কিছুটা দক্ষতার সাথে করা যেতে পারে However তবে এটি ছোট উপাদান আকারের জন্য কম দক্ষ হয়ে ওঠে; জায়ান্ট শেফেল-মাস্ক লকিং টেবিলগুলি কার্যকর নয়, এবং 32- এর চেয়ে কম সংখ্যক অ্যাভিএক্স 2 লেন-ক্রসিং শ্যাফেল নেই বিট উপাদানসমূহ: একটি 128 বি পিএসএইচএফবি সংস্করণটি বিএমআই 2 পেক্সট / পিডিইপি সহ ফ্লাইতে একটি মাস্ক তৈরি করতে সক্ষম হতে পারে , আপনি যেমন বড় আকারের অ্যাভিএক্স 2 এর জন্য পারেন তবে এটি মুশকিল কারণ 64-বিট পূর্ণসংখ্যায় কেবল 8 বাইট থাকে god গডবোল্ট লিঙ্ক এই উত্তরে এমন কিছু কোড রয়েছে যা উচ্চতর উপাদানগুলির জন্য কাজ করতে পারে))


আরএনজির বিলম্ব যদি একটি বাধা হয়ে থাকে তবে আমরা দুটি জেনারেটরের সমান্তরালে চালিয়ে আরও দ্রুত যেতে পারতাম, আমরা কোনটি ব্যবহার করি তা পরিবর্তিত করে। সংকলকটি এখনও অনিবন্ধিত লুপে নিবন্ধগুলিতে সহজেই সবকিছু রাখতে পারে এবং এটি দুটি নির্ভরশীল শৃঙ্খলাগুলিকে সমান্তরালে চালাতে দেয়।

বর্তমান সংস্করণে, পিআরএনজির আউটপুট কেটে, আমরা আসলে পোর্ট 0 থ্রুপুটটিতে পিআরএনজি ল্যাটেন্সি নয়, তবে তার প্রয়োজন নেই।


কোড: এভিএক্স 2 সংস্করণ

গডবোল্ট সংকলক এক্সপ্লোরারের আরও মন্তব্য সহ পূর্ণ সংস্করণ ।

খুব পরিপাটি নয়, দুঃখিত আমাকে ঘুমাতে হবে এবং এই পোস্টটি পেতে চাই।

SSE2 সংস্করণ পেতে থেকে s/_mm256/_mm, s/256/128/, s/v16u/v8u/, এবং পরিবর্তন vector_size(32)এছাড়াও 4 * 16 4 * 8 থেকে সম্পর্কে newline বৃদ্ধি পরিবর্তন 16. করতে। (যেমনটি আমি বলেছিলাম, কোডটি অগোছালো, এবং দুটি সংস্করণ সংকলনের জন্য ভালভাবে সেট আপ করা হয়নি AV মূলত একটি এভিএক্স 2 সংস্করণ তৈরি করার পরিকল্পনা করেনি, তবে তখন আমি সত্যিই আমার অ্যাক্সেস পেয়েছি এমন একটি হ্যাসওয়েল সিপিইউতে পরীক্ষা করতে চেয়েছিলাম))

#include <immintrin.h>
#include <unistd.h>
#include <stdint.h>
#include <stdio.h>
//#include <string.h>

// This would work equally fast 128b or 256b at a time (AVX2):
// https://stackoverflow.com/questions/24001930/avx-sse-version-of-xorshift128
struct rngstate256 {
    __m256i state0;
    __m256i state1;
};

static inline __m256i xorshift128plus_avx2(struct rngstate256 *sp)
{
    __m256i s1 = sp->state0;
    const __m256i s0 = sp->state1;
    sp->state0 = s0;
    s1 = _mm256_xor_si256(s1, _mm256_slli_epi64(s1, 23));
    __m256i state1new = _mm256_xor_si256(_mm256_xor_si256(_mm256_xor_si256(s1, s0),
                            _mm256_srli_epi64(s1, 18)),
                      _mm256_srli_epi64(s0, 5));
    sp->state1 = state1new;
    return _mm256_add_epi64(state1new, s0);
}



// GNU C native vectors let us get the compiler to do stuff like %10 each element
typedef unsigned short v16u __attribute__((vector_size(32)));

__m256i* vec_store_digit_and_space(__m256i vec, __m256i *restrict p)
{
    v16u v = (v16u)vec;
    v16u ten = (v16u)_mm256_set1_epi16(10);

    v16u divisor = (v16u)_mm256_set1_epi16(6554);  // ceil((2^16-1) / 10.0)
    v16u div6554 = v / divisor;      // Basically the entropy from the upper two decimal digits: 0..65.
    // Probably some correlation with the modulo-based values, especially dig3, but we do this instead of
    // dig4 for more ILP and fewer instructions total.

    v16u dig1 = v % ten;
    v /= ten;
    v16u dig2 = v % ten;
    v /= ten;
    v16u dig3 = v % ten;
    //  dig4 would overlap much of the randomness that div6554 gets

    const v16u ascii_digitspace = (v16u)_mm256_set1_epi16( (' '<<8) | '0');

    v16u *vecbuf = (v16u*)p;
    vecbuf[0] = div6554 | ascii_digitspace;
    vecbuf[1] = dig1    | ascii_digitspace;
    vecbuf[2] = dig2    | ascii_digitspace;
    vecbuf[3] = dig3    | ascii_digitspace;
    return p + 4;  // always a constant number of full vectors
}


void random_decimal_fill_buffer(char *restrict buf, size_t len, struct rngstate256 *restrict rngstate)
{
    buf = __builtin_assume_aligned(buf, 32);

    // copy to a local so clang can keep state in register, even in the non-inline version
    // restrict works for gcc, but apparently clang still thinks that *buf might alias *rngstate
    struct rngstate256 rng_local = *rngstate;

    __m256i *restrict p = (__m256i*restrict)buf;
    __m256i *restrict endbuf = (__m256i*)(buf+len);
    static unsigned newline_pos = 0;
    do {
        __m256i rvec = xorshift128plus_avx2(&rng_local);
        p = vec_store_digit_and_space(rvec, p);  // stores multiple ASCII vectors from the entropy in rvec

#if 1
        // this is buggy at the end or start of a power-of-2 buffer:
        // usually there's a too-short line, sometimes a too-long line
        const unsigned ncols = 100;
        newline_pos += 4*16;
        if (newline_pos >= ncols) {
            newline_pos -= ncols;
            char *cur_pos = (char*)p;
            *(cur_pos - newline_pos*2 - 1) = '\n';
        }
#endif
        // Turning every 100th space into a newline.
        // 1) With an overlapping 1B store to a location selected by a counter.  A down-counter would be more efficient
        // 2) Or by using a different constant for ascii_digitspace to put a newline in one element

        // lcm(200, 16) is 400 bytes, so unrolling the loop enough to produce two full lines makes a pattern of full vectors repeat
        // lcm(200, 32) is 800 bytes
        // a power-of-2 buffer size doesn't hold a whole number of lines :/
        // I'm pretty sure this can be solved with low overhead, like maybe 10% at worst.
    } while(p <= endbuf-3);

    *rngstate = rng_local;
}



#define BUFFER_SIZE (128 * 1024)
const static size_t bufsz = BUFFER_SIZE;
__attribute__((aligned(64))) static char static_buf[BUFFER_SIZE];

int main(int argc, char *argv[])
{
    // TODO: choose a seed properly.  (Doesn't affect the speed)
    struct rngstate256 xorshift_state = {
      _mm256_set_epi64x(123, 456, 0x123, 0x456),
      _mm256_set_epi64x(789, 101112, 0x789, 0x101112)
    };

    for (int i=0; i < 1024ULL*1024*1024 / bufsz * 100; i++) {
        random_decimal_fill_buffer(static_buf, bufsz, &xorshift_state);
        size_t written = write(1, static_buf, bufsz);
        (void)written;
        //fprintf(stderr, "wrote %#lx of %#lx\n", written, bufsz);
    }

}

জিসিসি, ঝনঝন, বা আইসিসি (অথবা আশা করি যে কোনও অন্য সংকলক যা সি 99 এর জিএনইউ সি ডায়ালেক্ট এবং ইন্টেলের অভ্যন্তরীণগুলি বোঝে) দিয়ে সংকলন করুন। জিএনইউ সি ভেক্টর এক্সটেনশানগুলি মডিউলার গুণক বিপরীত ব্যবহার করে বিভাগ / মডুলোর জন্য যাদু সংখ্যাগুলি তৈরি করতে সংকলকটি পেতে খুব সুবিধাজনক এবং মাঝে মাঝে __attribute__গুলি দরকারী।

এটি বহনযোগ্যভাবে লেখা যেতে পারে, তবে এটি আরও কোড লাগবে।


পারফরম্যান্স নোট:

নতুন লাইনগুলি সন্নিবেশ করানোর জন্য ওভারল্যাপিং-স্টোরটি কোথায় রাখবে তা স্থির করার জন্য গুরুত্বপূর্ণ শাখার ওভারহেড রয়েছে (শাখার ভুল ধারণা এবং কোর 2-এ সামনের বাধা), তবে স্টোর নিজেই কার্য সম্পাদনে কোনও প্রভাব ফেলেনি। সংকলকের অ্যাসেমের কেবল সেই স্টোর নির্দেশনা সম্পর্কে মন্তব্য করা (সমস্ত ব্রাঞ্চিং একই রেখে) একই সময়ে বার বার রান করা +1- এর চেয়ে কম 1% করার সাথে সাথে কোর 2 এর পারফরম্যান্সটি পুরোপুরি অপরিবর্তিত রয়েছে। সুতরাং আমি এই সিদ্ধান্তে পৌঁছেছি যে স্টোর বাফার / ক্যাশে এটি ঠিকঠাকভাবে পরিচালনা করে।

তবুও, ascii_digitspaceএকটি নতুন লাইনের সাথে থাকা একটি উপাদানগুলির সাথে কোনও ধরণের ঘোরানো উইন্ডো ব্যবহার করা আরও দ্রুত হতে পারে, যদি আমরা পর্যাপ্ত তালিকাভুক্ত না করি যে কোনও কাউন্টার / ব্রাঞ্চিং চলে যায়।


/ Dev / নালকে লেখা মূলত একটি অপ-অপশন, তাই সম্ভবত বাফার সম্ভবত এল 2 ক্যাশে গরম থাকে (হাসওলে প্রতি 256kiB কোর প্রতি)। 128 বি ভেক্টর থেকে 256 বি ভেক্টরগুলির নিখুঁত গতিপথ আশা করা হচ্ছে: কোনও অতিরিক্ত নির্দেশ নেই এবং সমস্ত কিছু (স্টোর সহ) দ্বিগুণ প্রস্থের সাথে ঘটে। যদিও নতুন লাইন সন্নিবেশ শাখাটি প্রায় দ্বিগুণ নেওয়া হয়। দুর্ভাগ্যক্রমে আমি আমার অংশওয়াল সাইগউইন সেটআপে অংশটি শেষ করেছিলাম #ifdefনা।

হাসওলে অ্যাভিএক্স 2-স্টোর প্রতি 2.5GHz * 32B / 13.7GB / s = 5.84 চক্র। এটি বেশ ভাল, তবে দ্রুত হতে পারে। সাইগউইন সিস্টেমের কলগুলির মধ্যে কিছুটা ওভারহেড থাকতে পারে যা আমি ভাবলি। আমি সংকলকের এসএম আউটপুটে তাদের মন্তব্য করার চেষ্টা করিনি (যা নিশ্চিত করে যে কিছুই অপ্টিমাইজড হবে না।)

এল 1 ক্যাশে প্রতি ঘন্টার জন্য একটি 32 বি স্টোর ধরে রাখতে পারে, এবং এল 2 খুব কম ব্যান্ডউইদথ নয় (যদিও উচ্চতর বিলম্বিতা)।

আমি যখন কয়েকটি সংস্করণ আগে আইএসিএর দিকে নজর দিয়েছিলাম (নিউলাইনগুলির জন্য শাখা ছাড়াই, তবে কেবল আরএনজি ভেক্টর অনুসারে কেবল একটি এএসসিআইআই ভেক্টর পাচ্ছিল), এটি প্রতি 4 বা 5 ক্লকের জন্য 32 বি ভেক্টর স্টোরের মতো কিছু ভবিষ্যদ্বাণী করেছিল।

এসএম xog ট্যাগ উইকিতে আমি লিঙ্ক যুক্ত করেছি বলে অ্যাগ্রার ফগের গাইড এবং অন্যান্য অপ্টিমাইজেশন সংস্থান বিবেচনা করে আমি নিজেই এএসএমটি দেখার উপর ভিত্তি করে প্রতিটি আরএনজি ফলাফল থেকে আরও তথ্য আহরণের থেকে আরও দ্রুতগতি অর্জনের আশা করছিলাম ))

স্কাইলেকে এটি সম্ভবত উল্লেখযোগ্যভাবে দ্রুততর হবে , যেখানে ভেক্টর ইন্টিজার মাল্টিপল এবং শিফটটি হ্যাসওয়েলের (কেবলমাত্র পি 0) তুলনায় দ্বিগুণ বহু পোর্ট (পি 0 / পি 1) চালাতে পারে। xorshift এবং অঙ্ক এক্সট্রাকশন উভয়ই অনেকগুলি শিফট এবং গুণক ব্যবহার করে। ( আপডেট: স্কাইলেক এটিকে 3.02 আইপিসিতে চালায়, আমাদের 32 জি বাইট এভিএক্স 2 স্টোর প্রতি 3.77 চক্র প্রদান করে , 1 জিবি পুনরাবৃত্তি প্রতি 0.030 সেকেন্ডে টাইম /dev/nullকরে লিনাক্স 4.15 এ i7-6700k এ 3.9GHz লিখে লিখেছেন)।


এটি ভাল কাজ করতে 64-বিট মোডের প্রয়োজন হয় না । সংকলিত করার সময় এসএসই 2 সংস্করণটি ঠিক তত দ্রুত -m32, কারণ এর জন্য খুব বেশি ভেক্টর নিবন্ধের প্রয়োজন হয় না, এবং সমস্ত 64-বিট গণিত ভেক্টরগুলিতে সম্পন্ন হয়, সাধারণ উদ্দেশ্যে নিবন্ধভুক্ত নয়।

এটি কোর 2-তে 32-বিট মোডে আসলে কিছুটা দ্রুত, কারণ তুলনা / শাখা ম্যাক্রো-ফিউশন কেবল 32-বিট মোডে কাজ করে, সুতরাং আউট-অফ-অর্ডার কোর (18.3s (1.85 প্রতি ঘড়ির প্রতি নির্দেশ)) বনাম কম ইউপ রয়েছে 16 16.9s (2.0 আইপিসি)। আরএক্স প্রিফিক্স না থাকা থেকে ছোট কোডের আকারটি কোর 2 এর ডিকোডারগুলিকে সহায়তা করে।

এছাড়াও, কিছু রেগ-রেজি ভেক্টর পদক্ষেপগুলি লোডের সাথে প্রতিস্থাপন করা হয়, যেহেতু সমস্ত ধ্রুবকগুলি ভেক্টর রেগুলিতে আর ঠিক করে না। যেহেতু এল 1 ক্যাশে থেকে লোড থ্রুপুট কোনও বাধা নয়, এটি আসলে সহায়তা করে। (যেমন set1(10): ধ্রুবক ভেক্টর দ্বারা গুণমান : movdqa xmm0, xmm10/ / pmullw xmm0, xmm1রূপান্তরিত হয় movdqa xmm0, [constant]/ pmullw xmm0, xmm1)) যেহেতু রেজি-রেজি মোভডকিউএ একটি ALU বন্দর প্রয়োজন, এটি আসল কাজটি সম্পন্ন করার সাথে প্রতিযোগিতা করে, তবে একটি এমওভিডিকিউএ লোড কেবল ফ্রন্ট-এন্ড ডিকোড ব্যান্ডউইথের জন্য প্রতিযোগিতা করে। (অনেক নির্দেশাবলীর মধ্যে একটি 4-বাইট ঠিকানা থাকলে REX উপসর্গগুলি সংরক্ষণ করে প্রচুর লাভ বাতিল হয়ে যায়।

যদি আ’লু মোভডকিউএ উপস সংরক্ষণ করা হয় তবে আসল লাভটি কোথা থেকে এসেছে তা আমি অবাক হব না, যেহেতু সীমানাটি 2.0 আইপিসির গড়ের সাথে রাখা উচিত।

এই সমস্ত পার্থক্যগুলি হ্যাসওয়েলে অদৃশ্য হয়ে যায়, যেখানে লুপব্যাক বাফার না হলে পুরো জিনিসটি ডিকোডড-ইউওপ ক্যাশে থেকে চালানো উচিত। ALU + শাখা ম্যাক্রো-ফিউশন উভয় মোডে কাজ করে নেহালেমের পরে।


6
আমি কেবলমাত্র আপনি কীভাবে বিষয়টিতে "বিস্ট মোড" এ চলেছেন তা ভালবাসি ! :) আরও গুরুত্বপূর্ণ বিষয়, আপনি যদি হার্ডওয়্যারটির খুব নিম্ন-স্তরের জ্ঞানকে কাজে লাগিয়ে সত্যিকারের প্রয়োজন বা সর্বাধিক কর্মক্ষমতা খুঁজে বার করতে চান তবে এটি কী ধরণের লাভের একটি দুর্দান্ত উদাহরণ। এছাড়াও, আমরা এখানে কেবল একটি থ্রেড ব্যবহার করছি; সর্বাধিক বর্তমান ডেস্কটপ এবং সার্ভার ইন্টেল / এএমডি প্রসেসর (এবং লাইটওয়েট ট্যাবলেট এবং এসবিসি-তে এমনকি এআরএম রয়েছে) এর একাধিক কোর রয়েছে, তাই এখনও আরও বাস্তব-সময়-গ্রহণযোগ্য স্পীডআপ উপলব্ধ রয়েছে। এবং পরিশেষে, নিখুঁত প্রচেষ্টা জড়িত থাকার কারণে প্রশ্নগুলি কতটা অবৈধ "দ্রুততমতম উপায়"
নামমাত্র প্রাণী

1
@ নোমিনাল অ্যানিমাল: হ্যাঁ, এমনকি ধীর এআরএম কোয়াড বা অক্টোটোর কোরও সহজেই প্রধান স্মৃতি ব্যান্ডউইদথকে একই জিনিস NEON এর সাথে পরিপূর্ণ করে তুলতে পারে (এমনকি তাদের দ্রুত ডুয়েল চ্যানেল ডিডিআর 3 এ সংযুক্ত করা হয়েছিল), যদি এতে -৪-বিট পূর্ণসংখ্যার সিমড যোগ হয় এবং শিফট থাকে । আমি ধরে নিই নিওনে অডিও কাজের জন্য 16-বিট উপাদান-আকারের গুণিত রয়েছে। অর্ডার-এআরএমের জন্য নির্দেশ-সময়সূচী আরও অনেক বেশি কাজ হবে, কারণ লুপ বহনকারী নির্ভরতা শৃঙ্খলের প্রতিটি পুনরাবৃত্তি (xorshift128 +) সেই কাটা এবং স্মৃতিতে সংরক্ষণ করার জন্য কয়েকটি স্বাধীন নির্ভরশীল শৃঙ্খলা ফিড করে ...
পিটার কর্ডস

... আদেশ-বহির্গমন কার্যকর নাশতার জন্য এটি খায়, কারণ পুরো জিনিসটি যথেষ্ট সংক্ষিপ্ত যে বেশ কয়েকটি পুনরাবৃত্তি আরওবিতে ফিট করে (এইচএসডাব্লু আইআইআরসি-র 192 উফ)। (উদাহরণস্বরূপ, আদেশের "উইন্ডো" যা আদেশ ছাড়াই কার্যকর হয় তা একাধিক পুনরাবৃত্তি অন্তর্ভুক্ত করে)। সুতরাং সিপিইউ 2 বা 3 পুনরাবৃত্তির আগে চূড়ান্ত স্টোরটি সমাপ্ত করতে পারে যখন বর্তমান পুনরাবৃত্তির শুরুতেও শুরু হচ্ছে। এটি স্বতন্ত্র চেইনের বিলম্বকে আড়াল করে, তাই কেবল থ্রুপুট বিষয়গুলি। একটি অর্ডার অর্ডারে, এর জন্য সফ্টওয়্যার পাইপলাইনের প্রয়োজন হবে ...
পিটার কর্ডেস

... একটি ভাল এআরএম সংকলক আপনার জন্য কিছু করা উচিত যদি আপনি এটি অন্তর্ভুক্ত দিয়ে লিখেন (বা পুরো জিনিসটির জন্য জিএনইউ সি নেটিভ ভেক্টর সিনট্যাক্স, যেমন আমার প্রথম স্থানটি করা উচিত ছিল)। বাস্তবের জন্য এটি করার আমার কোনও অভিজ্ঞতা নেই, সুতরাং আপনাকে আপনার লুপটি ম্যাসেজ করতে হবে এবং ভাল অ্যাসেম পাওয়ার জন্য উত্সটিতে কিছু ম্যানুয়াল আনারোলিং / সফ্টওয়্যার-পাইপলাইনিং করার দরকার হতে পারে। (উচ্চ-প্রান্তের ফোনে পাওয়া কিছু অ-অফ-অর্ডার-এআরএম কোর রয়েছে, তবে তাদের কাছে হ্যাসওয়েলের মতো আউট-অফ-অর্ডার উইন্ডো নেই O ওওহো, তাদের নীচের শিখর থ্রুপুটও আছে, তাই কম আছে) আরও আইএলপি সন্ধান থেকে লাভ করতে)।
পিটার কর্ডেস

1
@ নোমিনালঅনিমাল: এছাড়াও, প্রশ্নের বোকামি নিয়ে সম্মত হয়েছেন। এলোমেলো মানের মানের কোনও বাধা ছাড়াই "দ্রুততম" নির্বোধ ... বিটিআরএফএসের সাথে, ডিস্কে একই ডেটা একাধিকবার কোনও ফাইলের অংশ হতে পারে ( ৪.২-এ এক্সটিটিসেমেম দেখুন )। সুতরাং আপনি একটি এলোমেলো 4kiB বা 1MB উত্পাদন করতে এবং এটি পুনরাবৃত্তি করতে পারেন। এটি একটি স্বল্প সময়ের সাথে এলোমেলো, তবে এটি এখনও এলোমেলো, এবং কেবলমাত্র মেটাডেটা I / O এর জন্য ব্যয় করে। (প্রকৃতপক্ষে, আপনাকে একটি নতুন লাইন দিয়ে শেষ হওয়ার জন্য ব্লকটি দরকার l lcm (4096, 4096 * 200) = 4096 * 200 = 819200 = 800kiB, সুতরাং আপনার পুনরাবৃত্তি ব্লকটি এর কোনও একাধিক।)
পিটার

14

এখানে একটি সমাধান যা আমি আশা করি এটি বুঝতে সহজ:

od -An -x /dev/urandom | tr -dc 0-9 | fold -w100 | awk NF=NF FS= | head -c1G
  • odথেকে হেক্সাডেসিমাল ডিজিটের একটি অভিন্ন স্ট্রিম তৈরি করে /dev/random
  • trঅক্ষর থেকে মুক্তি পাওয়া যায়, কেবল 0-9সংখ্যা রাখে
  • fold লাইন প্রতি 100 সংখ্যা আছে তা নিশ্চিত করে
  • awk লাইনের ভিতরে ফাঁকা স্থান সন্নিবেশ করায়
  • head ইনপুটটি 1 গিগাবাইটে কেটে দেয়

2
এটি একটি অভিন্ন বিতরণ থাকা সত্ত্বেও / dev / এলোমেলোভাবে বাইট দ্বারা একাধিক সংখ্যার উত্পাদনের এক দুর্দান্ত বিকল্প উপায়, যা গড়ে প্রতি 256 বাইট / dev / urandom এর জন্য 320 ডিজিট তৈরি করে (যখন আপনি বাইট <200 মডিউল রূপান্তর করেন তখন কম 100 থেকে দশমিক যা আপনাকে প্রতি 256 বাইটের জন্য 400 ডিজিট দেয়)।
স্টাফেন চেজেলাস

6

আপনি এর jotজন্য কমান্ডটি ব্যবহার করতে পারেন :

jot -r 50000000 0 9 | fmt -w 200 > output.txt

1
@ ডিজিটালট্রামুমা আমার সংস্করণটির fmtলক্ষ্য প্রস্থের বিকল্প নেই। যাইহোক, এটি সঠিক হবে কারণ সমস্ত অঙ্কগুলি হ'ল একটি কলাম নেয়!
বাগান মাথা

রেকর্ডের জন্য আমার fmtসংস্করণটি হ'ল fmt (GNU coreutils) 8.25(উবুন্টু 16.04)
ডিজিটাল ট্রমা

2
অর্ধ গিগাবাইটের জন্য সঠিক সংখ্যাটি হ'ল: 1024 * 1024 * 536870912
1024/2

1
@ অলিভিয়ারডুলাক নির্ভর করে আপনি যে "গিগাবাইট" এর কথা বলছেন। কিছু লোক প্রযুক্তিগতভাবে ত্রুটিযুক্ত থাকা সত্ত্বেও 2 ^ 30 এর পরিবর্তে 10 ^ 9 বোঝাতে 1 জিবি ব্যবহার করে। প্লাস আমি সুন্দর গোল সংখ্যাগুলি পছন্দ করি :)
বাগানের মাথা

6
@ গার্ডেনহেড, আরও অনেক বেশি লোক এখন গিগাবাইট == 1e9 এবং গিবিবিট == 2 ^ 30 এ চলেছে আইইসি স্ট্যান্ডার্ড সংজ্ঞা হিসাবে। উইকিপিডিয়া দেখুন । মনে রাখবেন যে গিগাবাইট নিজেই গিগা বিট হবে
স্টাফেন চেজেলাস

6

এটি স্টাফেন চেজেলাস পদ্ধতির অনুরূপ, তবে আমি পারফরম্যান্সের উন্নতি করতে একবারে 64 বিট পড়ি। বিতরণটি এখনও অভিন্ন তবে এখন আপনি আগের মতো সেরা ক্ষেত্রে কেবল 8 এর পরিবর্তে প্রতি 8 বাইটের জন্য 19 সংখ্যা পাবেন

perl -nle 'BEGIN{$/=\8; $,=" "}
           $n = unpack("Q");
           next if $n >= 10000000000000000000;
           $s = sprintf("%019u", $n);
           push @a, (split //, $s);
           if (@a >= 100) {print (splice @a, 0, 100);}' < /dev/urandom | head -c1G

32-বিট প্ল্যাটফর্মে 19 সংখ্যার পরিবর্তে প্রতিবার 9 অঙ্ক পড়তে হবে।


আপনার সিস্টেম 64৪-বিট পূর্ণসংখ্যার সমর্থন না করে বা perlকোয়াড সমর্থন দিয়ে সংকলিত না হলে এটি ব্যতিক্রম বাড়াতে পারে ।
cuonglm

@ কুওগলম হ্যাঁ যেমন আমি বলেছি পার্ল যদি সেই সিস্টেমে b৪ বিট না হয় তবে প্রোগ্রামটি পরিবর্তন next if $n >= 1000000000; $s = sprintf("%09u", $n);করতে হবে মাত্র ৯ ডিজিটের জন্য
ফুক্লভ

আপনি পারবেন না, $n = unpack("Q")কোয়াড সমর্থিত না হলে প্রোগ্রামটি ক্রাশ হবে ।
cuonglm

1
@cuonglm পরিবর্তনের BEGIN{$/=\4; $,=" "} $n = unpack("L");এছাড়াও
phuclv

1
দুঃখিত, তবে এটি 8 বাইট ইনপুট থেকে 19 টি সংখ্যা পেয়েছে কেবল সময়ের প্রায় 54.2% এবং বাকী কোনওটিই নয়, প্রতি ইনপুট বাইটের গড় 1.29 ডিজিট। আপনি যদি আরও বেশি স্টিফেন ব্যবহার করেন <16e18এবং 16 দ্বারা ভাগ করেন তবে আপনি 1.95 ডিপিবি-র জন্য 18 ডিজিটের 86.7% পাবেন। 32 বিট সহ, <4e9 /4২.১০ ডিপিবি-র জন্য 9 ডিজিট 93.1% পায়। তবে 5 বাইট (হেক্স হিসাবে (এইচ 10)) <1e1212 ডিজিট 90.9% দেয় 2.18 ডিপিবি এর জন্য, বা অর্ধেক অংশে হেক্সকে বিভক্ত করে এবং প্রতিটি অর্ধেকটি <1e6 ২.২৯ ডিপিবি-র জন্য digit সংখ্যার 95.4% দেয়; এটি লগ_10 (256) = 2.41 এর সীমাতে পৌঁছেছে।
dave_thompson_085

3

আপনার যদি গতির প্রয়োজন হয় তবে একটি সংকলিত প্রোগ্রামিং ভাষা ব্যবহার করার জন্য আমি নমিনাল অ্যানিমালের সাথে একরকম একমত। যাইহোক, আপনাকে সিটিতে নিজের আরএনজি কোড লিখতে হবে না +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++> সি ++++++++++++++++++++++++++++++++++++++++++++ এর জন্য সি সি ++ তে আপনার নিজের আরএনজি কোড লিখতে হবে না standard

#include <time.h>
#include <random>
#include <iostream>
using namespace std;

int main() {
    mt19937 gen(time(0)); 
    uniform_int_distribution<> dist(0,9);

    for(int j=0; j<5000000; j++){
        for (int i = 0; i < 99; i++) {  
            cout << dist(gen) << " ";
        }  
        cout << dist(gen) << endl;
    }
    return 0;
}

উপরের কোডটি যুক্তিসঙ্গতভাবে সহজ এবং যখন আমি কোনও ফাইলে আউটপুট পাইপ করি তখন প্রায় এক মিনিট সময় লাগে। 100 ডিজিটের জন্য যথেষ্ট বড় স্ট্রিং তৈরি করে এবং এর মধ্যে অঙ্কগুলি হ্যাক করে আমরা আরও দ্রুত যেতে পারি। এটি আমাদের প্রতিটি অঙ্কের পরিবর্তে প্রতিটি লাইনকে কল করতে সহায়তা করে।

#include <time.h>
#include <random>
#include <iostream>
using namespace std;

int main() {
    mt19937 gen(time(0)); 
    uniform_int_distribution<> dist(0,9);

    char line[201];
    for(int i=1; i<199; i++)
        line[i] = ' ';
    line[199] = '\n';
    line[200] = 0;

    for(int j=0; j<5000000; j++){
        for (int i = 0; i < 199; i += 2) {  
            line[i] = dist(gen)+'0';
        }  
        cout << line;
    }
    return 0;
}

এই কোডটি আমার মেশিনটি প্রায় ছয় সেকেন্ড সময় নেয়। মনে রাখবেন এটি স্ট্যান্ডার্ড আউটপুট, তাই এটি একটি ফাইলে পাইপ করুন।

আমার কাছে বেশ কয়েকটা অস্বীকৃতি রয়েছে। প্রথমত, আমি এটি একটি উইন্ডোজ পিসিতে লিখছি। আমি মনে করি লাইব্রেরিগুলি সমস্ত লিনাক্সে উপস্থিত রয়েছে, তবে আমি যদি ভুল হয়ে থাকি তবে অবশ্যই এটি উল্লেখ করতে ভুলবেন না।

এছাড়াও, এটি আসলে অর্ধ বিলিয়ন স্থান পৃথক অঙ্কগুলি আউটপুট করে, যা প্রযুক্তিগতভাবে একটি গিগাবাইট তবে সম্ভবত আপনি যা চেয়েছিলেন ঠিক তা নয়। এটি 5 মিলিয়ন লাইন, প্রতি লাইন 100 ডিজিট আউটপুট করে। পার্থক্যটি গুরুত্বপূর্ণ হলে, আপনি লাইনের সংখ্যা বাড়াতে পারেন। আমার উইন্ডোজ বাক্সে ফাইলটি 10 ​​^ 9 বাইটের চেয়ে কিছুটা বড় বলে মনে হচ্ছে, যা আমি অতিরিক্ত নিউলাইন অক্ষরের সাথে করণীয় বলে মনে করি।


2
আরে, সমালোচনা আসলেই ন্যায্য নয়! :) আমার প্রোগ্রামের বেশিরভাগটি হ'ল কমান্ড-লাইন প্যারামিটার পার্সিং। যদি আমি মন্তব্য, ত্রুটি চেক এবং কলাম এবং লাইন আউটপুট সংখ্যা হার্ডকোড বাদ দিই, তবে আমি এটিকে আপনার কোডের আকারের দ্বিগুণেরও কম করতে পারি - খুব কমই মাসিক । :) একসাথে মজা করা: হ্যাঁ, বেশিরভাগ লিনাক্স বিতরণে গ্রন্থাগারগুলি উপলব্ধ। আমার ল্যাপটপে, আপনার লাইন-এ-এ-সময়ে প্রায় 14 সেকেন্ড সময় লাগে, অন্যদিকে আমার লাইন-এ-এ-টাইম সংস্করণটি মাত্র 1.3 সেকেন্ড নেয়। পার্থক্যটি কেবলমাত্র পিআরএনজির কারণে: মার্স্নে টুইস্টার জোরশিফট *৪ * এর চেয়ে অনেক ধীর।
নামমাত্র প্রাণী

1
আমি একটি ব্যবহারিক জিনিসটি উল্লেখ করতে চাই যে আপনি মিস করেছেন, তবে আমি আশা করি আপনি এটিকে নেতিবাচকতা হিসাবে গ্রহণ করবেন না, কেবল কিছু ভাবার জন্য: আমি আমার উত্তরে যেমন উল্লেখ করেছি, এক-শট প্রোগ্রামগুলি খুব কমই মূল্যবান সময় তারা লিখেছে। এজন্য কমান্ড-লাইন পার্সিং এবং সহায়তা ব্যবহারের পাঠ্য প্রায় যোগ করা সার্থক। আমার কাছে এই জাতীয় ইউটিলিটি প্রোগ্রামের একটি বিশাল সেট রয়েছে এবং তাদের প্রত্যেকে কী করে তা জানার জন্য তাদের উত্সগুলি অনুসন্ধান করার পরিবর্তে আমি কেবল এগুলি চালিত করি, সুতরাং তারা আমাকে বলবে; এবং আমি একাধিক প্রয়োজন অনুসারে তাদের আচরণটি যথেষ্ট পরিমাণে সংশোধন করতে পারি। বর্ধিত উন্নয়ন ব্যয়।
নামমাত্র প্রাণী

@ নমুনালঅনিমাল আরেকটি গুরুত্বপূর্ণ বিষয় হ'ল আপনি আউটপুটটি পাইপ করেছেন /dev/nullযা কোনও আসল ফাইলটিতে লেখার চেয়ে অনেক দ্রুত হবে
ফুক্লাভি

@ লুভানহফ্যাক: ঠিক আছে, সত্যিই নয়। এই ল্যাপির স্যামসুং 128 গিগাবাইট এসএসডি রয়েছে, যেখানে 500 এমবি / এসের সিক্যুয়ালিটি পড়ে এবং লিখেছে। একটি লিনাক্স সফটওয়্যার-RAID0 কনফিগারেশনে চারটি রাখুন এবং এত বড় ডেটাসেট জেনারেট করার সময় আপনি দ্বিতীয় গিগাবাইটের চেয়ে ভাল পড়তে পারবেন (আমার অনুমান ~ 1.75 টিবি / গুলি)। 1GB / s বহু বছর আগে লিনাক্স sw-RAID0 এর সাথে 12 এসটিএ ড্রাইভ (স্পিনিং প্লাটার এমনকি এসএসডি নয়) দিয়ে পৌঁছেছিল। (দ্রষ্টব্য: বাইটস / গুলি, বিটস / গুলি নয়।) অবশ্যই, এটি একটি "সাধারণ" মেশিনের জন্য নির্বোধ শোনায়, তবে যারা বড় ডেটাসেট নিয়ে খেলেন, তারা তা সার্থক মনে করেন - আপনি যা কিছু করেন তা থেকে সময় শেভ করেন (বড় ডেটাসেট সহ) ঐ দিকে.
নামমাত্র প্রাণী

1
@ নোমিনালঅ্যানিমাল এবং লুউ: আরও গুরুত্বপূর্ণ বিষয়, আপনার যদি পর্যাপ্ত র‍্যাম থাকে তবে ডেটা সমস্ত ডিস্কে রাখার আগেই প্রোগ্রামটি ভালভাবে বেরিয়ে যেতে পারে। বৃহত write()সিস্টেমে কল করার বেশিরভাগ কাজ হ'ল পেজকেচে মেমকি থাকে যা কার্নেল আরও বাফার স্থান বরাদ্দের পরিবর্তে এটি করার সিদ্ধান্ত নেয় কেবল তখনই অবরোধ করে। এই প্রোগ্রামটি কেবলমাত্র ডিস্ক আই / ও-তে বাধা দিতে হবে যখন মেমরিটি শক্ত থাকে বা আপনি যদি পৃষ্ঠার ক্যাশে বাইপাস করতে O_DIRECT ব্যবহার করে থাকেন। আপনি যদি write()ক্যাশে আকারের চেয়ে ছোট অংশে থাকেন, আশা করি আপনার ডেটা একবারে মূল স্মৃতিতে চলে গেছে এবং সেই জায়গায় আবার লেখা বাফারটি L2 বা L3 ক্যাশে গরম থাকে।
পিটার কর্ডেস

1

এটি আপনার "এলোমেলো" সংজ্ঞাটির উপর নির্ভর করে। যদি আপনি ক্রিপ্টোগ্রাফিকভাবে এলোমেলো বলতে চান তবে আপনাকে কেবল একটি ভাল গ্রন্থাগার পেতে হবে এবং বুলেটটি কামড়তে হবে, এটি চালানোর জন্য অপেক্ষা করুন।

আপনার যদি এমন কিছু প্রয়োজন হয় যা দেখতে বেশ এলোমেলো লাগে তবে এখানে একটি সহজ উপায়:

  1. বেশ কয়েকটি জিবি দীর্ঘ একটি ফাইল পান। আপনার প্রিয় সিনেমা ভাল হবে।
  2. এটি জিপ করুন, বারবার নিদর্শনগুলি আটকানোর একটি সহজ উপায়
  3. ফাইলটি একবারে একটি আঁচল (আধা বাইট) মাধ্যমে যান। প্রতিটি মান 0 এবং 15 এর মধ্যে হবে 1 10 এর চেয়ে কম 1 বা তার চেয়ে বেশি দূরে নিক্ষেপ করুন প্রথম বিলিয়ন বেঁচে যাওয়া প্রত্যেকের কাছ থেকে 1 বিয়োগ করুন এবং এটি একটি অঙ্ক হিসাবে লিখুন।

ধীর মেশিনে চালাতে এক ঘন্টা সময় নিতে পারে; বেশিরভাগ উদ্দেশ্যে দ্রুত এবং এলোমেলো যথেষ্ট।


9
/dev/urandomgzipগতি এবং এলোমেলোভাবে উভয়ের চেয়ে ভাল হওয়ার সম্ভাবনা রয়েছে ।
স্টিগ হেমার

Get a file that is several Gb long1 জিবি ফাইল আনার জন্য আপনার একটি ফাইলের প্রয়োজন ** কমপক্ষে 8 গিগাবাইট
ফুলচলভি

1
#!/bin/bash
FILE_CREAT='/tmp/testfile'
MAX_SIZE=$(( 1 * 1024 * 1024 ))
rm -rf ${FILE_CREAT}
while true
do
    STRING=''
    for (( i = 0 ; i < 100 ; i++ ))
    do
        NUM_RAN=$(cat /dev/urandom | tr -dc 0-9 | head -c 1)
        if [ $i -eq 0 ]
        then
            STRING=${NUM_RAN}
        else
            STRING=${STRING}' '${NUM_RAN}
        fi
    done
    echo ${STRING} >> $FILE_CREAT
    FILE_SIZE=$(du -s ${FILE_CREAT} | awk '{print $1}')
    if [ ${FILE_SIZE} -ge ${MAX_SIZE} ]
    then
        break
    fi
done
exit $1

1
সাইটে স্বাগতম! আমার প্রোফাইল পৃষ্ঠায় লিঙ্কগুলি দেখুন। এখানে দুর্দান্ত অনেকগুলি সমস্যা রয়েছে যা আমি শেল স্ক্রিপ্টগুলিতে প্রায় সর্বজনীনভাবে দেখি, তবে এটি তাদের সঠিক করে না।
ওয়াইল্ডকার্ড

2
@ উইল্ডকার্ড: কখন cat file | trযখন আপনি ঠিক করতে পারবেন না tr <file। আইআইআরসি, আপনি এমনকি করতে পারেন <file tr। আমি ভেবেছিলাম আপনি কেবল এই শেল স্ক্রিপ্টটি সম্পর্কে বলছেন du | awkযে আকারটি পরীক্ষা করার জন্য প্রতিটি লাইনের পরে ক্লানকি এবং ধীর দেখাচ্ছে এবং লুপের বাইরে পুনর্নির্দেশের পরিবর্তে প্রতিটি লাইন সংযুক্ত করার জন্য ফাইলটি পুনরায় খোলার জন্য।
পিটার কর্ডেস

2
@ পিটারকর্ডস, হ্যাঁ পাঠ্যকে প্রক্রিয়াজাত করতে শেল লুপ ব্যবহার করা খারাপ অভ্যাস হিসাবে বিবেচনা করা হয় কেন? বিশেষভাবে প্রাসঙ্গিক — এই স্ক্রিপ্টটি এমন ধারণার উপর ভিত্তি করে তৈরি করা হয়েছে যে বাশ সি এর মতো একটি প্রোগ্রামিং ভাষা, যা এটি নয়। তবে, \ @ নমনটিটি, আমি আশা করি আপনি এই সাইটে আটকে থাকবেন কারণ এটি স্পষ্ট যে আপনার খুব যৌক্তিক মন রয়েছে। :)
ওয়াইল্ডকার্ড

4
@ পিটারকর্ডস cat /dev/urandom | busy-cmdএমন একটি বিরল ক্ষেত্রে যেখানে এটি বোধগম্য হতে পারে কারণ এটি এলোমেলো প্রজন্মকে বিভক্ত করতে পারে এবং প্রসেসরের মধ্যে ব্যস্ত সিএমডি বানাতে পারে। টিআরের পক্ষে তেমন কিছু নয় তবে odউদাহরণস্বরূপ স্যামের জন্য একটি পার্থক্য তৈরি করে ।
স্টাফেন চেজেলাস

1
@ স্টাফেনচাজেলাস: ঠিক আছে !! হ্যাঁ, রিড () সিস্টেম কলটি যেখানে আরএনজি সিপিইউ সময় ব্যয় করে।
পিটার কর্ডেস
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.