Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/file/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/73.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 我为班级写了这个汉明编码。为什么这么慢?_C++_File_Operating System_Hamming Code - Fatal编程技术网

C++ 我为班级写了这个汉明编码。为什么这么慢?

C++ 我为班级写了这个汉明编码。为什么这么慢?,c++,file,operating-system,hamming-code,C++,File,Operating System,Hamming Code,我为我的操作系统类写了以下内容: #include <iostream> #include <fstream> //encodes a file using the (8,4) Hamming Code. //usage : HammingEncode.out < inputFile > outputFile int main() { unsigned char const codebook[] = {0x00, 0x1E, 0x2D, 0x33,

我为我的操作系统类写了以下内容:

#include <iostream>
#include <fstream>

//encodes a file using the (8,4) Hamming Code.
//usage : HammingEncode.out < inputFile > outputFile 
int main() {
    unsigned char const codebook[] = {0x00, 0x1E, 0x2D, 0x33, 0x4B, 0x55, 0x66, 0x78, 0x87, 0x99, 0xAA, 0xB4, 0xCC, 0xD2, 0xE1, 0xFF};
    unsigned char in, nextByte;
    unsigned char const leftMask = 0xF0, rightMask = 0x0F;

    in = std::cin.get();
    while (!std::cin.eof()) {
        nextByte = (in & leftMask) >> 4;
        std::cout << codebook[nextByte];
        nextByte = in & rightMask;
        std::cout << codebook[nextByte];
        in = std::cin.get();
    }
}
#包括
#包括
//使用(8,4)汉明码对文件进行编码。
//用法:hammingecode.outoutputFile
int main(){
无符号字符常量码本[]={0x00、0x1E、0x2D、0x33、0x4B、0x55、0x66、0x78、0x87、0x99、0xAA、0xB4、0xCC、0xD2、0xE1、0xFF};
未签名字符输入,下一字节;
无符号字符常量leftMask=0xF0,rightMask=0x0F;
in=std::cin.get();
而(!std::cin.eof()){
nextByte=(in&leftMask)>>4;

std::cout若我理解正确,对于读取的每个字节,您将写入2个字节。所以输出文件的大小将是输入的两倍。若您的输入足够大,则总IO(读取+2*写入)时间将非常重要

在哈夫曼编码中,情况并非如此——因为您通常写的比读的少,并且总IO时间要少得多

编辑: 正如Blorgbeard所说,它可以是缓冲的区别。C++也可以缓冲,但默认缓冲区要比java小很多,而且HDD头应该在一个位置读文件,然后在另一个位置上写入,这会显著影响整个IO性能。
在任何情况下,编码都应该分块进行,以确保大数据块的顺序读写

C++iostream被认为效率很低,尽管不同的数字表明这是实现质量问题,而不是iostream的缺点

无论如何,只是为了确保它不是慢硬盘,你可以比较执行时间,例如

cat file1 > file2
当然,cource
cat
会更快一些,因为它不会使数据的大小增加一倍

然后尝试将代码的效率与以下内容进行比较:

#include <stdio.h>
#include <unistd.h>

int main()
{
    unsigned char buffer[1024*1024]; // 1MB buffer should be enough

    while (!eof(STDIN_FILENO)){
        size_t len = read(STDIN_FILENO, &buffer[0], 1024*1024);
        write(STDOUT_FILENO, &buffer[0], len);
        write(STDOUT_FILENO, &buffer[0], len);
    }

    return 0;
}
#包括
#包括
int main()
{
无符号字符缓冲区[1024*1024];//1MB缓冲区应该足够了
而(!eof(标准文件号)){
size\u t len=read(标准文件号和缓冲区[0],1024*1024);
写入(标准输出文件号和缓冲区[0],len);
写入(标准输出文件号和缓冲区[0],len);
}
返回0;
}
编辑:

对不起,我的错。试试看

#include <stdio.h>
#include <unistd.h>

int main()
{
    unsigned char buffer[1024*1024]; // 1MB buffer should be enough

    size_t len = read(STDIN_FILENO, &buffer[0], 1024*1024);

    while(len > 0){
        write(STDOUT_FILENO, &buffer[0], len);
        write(STDOUT_FILENO, &buffer[0], len);
        len = read(STDIN_FILENO, &buffer[0], 1024*1024);
    }

    return 0;
}
#包括
#包括
int main()
{
无符号字符缓冲区[1024*1024];//1MB缓冲区应该足够了
size\u t len=read(标准文件号和缓冲区[0],1024*1024);
而(len>0){
写入(标准输出文件号和缓冲区[0],len);
写入(标准输出文件号和缓冲区[0],len);
len=read(标准文件号和缓冲区[0],1024*1024);
}
返回0;
}

std::cin
是以文本模式打开的,因此它一直在寻找各种需要注意的东西(如换行符等)

考虑到
std::cin
输入流不断地进行字符嗅探,我并不惊讶它需要更长的时间,但它似乎有点过度。下面,绕过
iostream
并直接使用
FILE
流可能会达到您所期望的效果:

#include <cstdlib>
#include <cstdio>

int main(int argc, char *argv[])
{
    static unsigned char const codebook[] =
    {
        0x00, 0x1E, 0x2D, 0x33, 0x4B, 0x55, 0x66, 0x78,
        0x87, 0x99, 0xAA, 0xB4, 0xCC, 0xD2, 0xE1, 0xFF
    };

    for (int c = std::fgetc(stdin); c!=EOF; c=std::fgetc(stdin))
    {
        std::fputc(codebook[c >> 4], stdout);
        std::fputc(codebook[c & 0x0F], stdout);
    }

    return EXIT_SUCCESS;
}
使用
std::cin
std::cout

time ./hamming < bigfile.txt > bigfile.ham
real 0m23.819s
user 0m7.416s
sys  0m16.377s
time ./hamming < bigfile.txt > bigfile.ham
real 0m24.867s
user 0m7.705s
sys  0m17.118s
总而言之,哎哟。值得注意的是在系统中花费的时间。如果我有机会用
std::istream::get()
put()
方法来更新这个,我会的,但老实说,我不希望在这方面有任何奇迹。除非有魔法(对我,而不是对其他人)从
std::cin
文件流关闭io xlat的方法可能是一个合理的选择。我还没有研究slurping
std::cin
rdbuf()
是否是一个可行的选择,但它也可能有希望


编辑:使用
std::istreambuf\u迭代器

time ./hamming < bigfile.txt > bigfile.ham
real 0m23.819s
user 0m7.416s
sys  0m16.377s
time ./hamming < bigfile.txt > bigfile.ham
real 0m24.867s
user 0m7.705s
sys  0m17.118s
使用streambuf迭代器类有显著的改进,因为它基本上绕过了所有内联slat垃圾,但它仍然不如
文件
流那样有效:

#include <iostream>
#include <cstdlib>
#include <cstdio>

int main(int argc, char *argv[])
{
    static unsigned char const codebook[] =
    {
        0x00, 0x1E, 0x2D, 0x33, 0x4B, 0x55, 0x66, 0x78,
        0x87, 0x99, 0xAA, 0xB4, 0xCC, 0xD2, 0xE1, 0xFF
    };

    std::istreambuf_iterator<char> cin_it(std::cin), cin_eof;
    std::for_each(cin_it, cin_eof, [](char c)
        {
          std::cout.put(static_cast<char>(codebook[static_cast<unsigned char>(c) >> 4]));
          std::cout.put(static_cast<char>(codebook[static_cast<unsigned char>(c) & 0x0F]));
        });

    return EXIT_SUCCESS;
}
正如你所料,结果是可怕的:

time ./hamming < bigfile.txt > bigfile.ham

real 0m26.509s
user 0m2.370s
sys  0m24.087s
time./hammingbigfile.ham
真正的0m26.509s
用户0m2.370s
系统0m24.087s

我做了两个小改动,几乎提高了一个数量级

  • 添加
    std::ios\u base::synch\u与\u stdio(false)
    (没有明显区别,尽管影响通常是特定于实现的)
  • 在写入之前缓冲输出(这产生了最大的差异)
  • 更新后的代码如下所示:

    int main()
    {
    
        //encodes a file using the (8,4) Hamming Code.
        //usage : HammingEncode.out < inputFile > outputFile 
            unsigned char const codebook[] = { 0x00, 0x1E, 0x2D, 0x33, 0x4B, 0x55, 0x66, 0x78, 0x87, 0x99, 0xAA, 0xB4, 0xCC, 0xD2, 0xE1, 0xFF };
            unsigned char in, nextByte;
            unsigned char const leftMask = 0xF0, rightMask = 0x0F;
            std::stringstream os;
    
            std::ios_base::sync_with_stdio(false);
            in = std::cin.get();
            while (std::cin) {
                nextByte = (in & leftMask) >> 4;
                os.put(codebook[nextByte]);
                nextByte = in & rightMask;
                os.put(codebook[nextByte]);
                in = std::cin.get();
            }
            std::cout << os.rdbuf();
    }
    

    嗯,是的。但是我不明白为什么写一个文件要比直接用Java写一个文件花两倍的时间。比如说,如果我用Java写两次这个文件,速度会快得多。所以我想知道为什么这段代码要花30秒来写8MB的8MB的8MB的30秒听起来确实很慢。我会尝试实验:试着只读一读一个字节接一个字节的文件,对于每个字节,只需将读取的字节写入输出文件两次。这样可以了解问题是在IO中还是在算法本身(不太可能)。但重要的是读取字节,然后立即写入两次(不要读取缓冲区,然后写入缓冲区两次)@DenisItskovitch我不确定我是否知道如何在不使用iostream的情况下直接写,iostream是缓冲区。我不能做nextByte=std::cin.get()&rightMask;std::cout@JonCohen我不是指直接写。我的意思是像你在问题中所做的那样读/写,但没有编码尝试,所用的时间也一样长:(很可能是java在为您缓冲输入和输出。您在这里一次读取/写入一个字节。@Blorgbeard iostream也在缓冲。@j_kubik我可以更正。您的编译标志是什么?在这种情况下,未优化的代码会非常慢,但优化有可能将其加速几个数量级。@j_kubik g++HammingCode.cpp-O2-o HammingCode.out这不编译,它不识别eof。我用feof替换了它并编译了它,但给了我一个segfault。
    static\u cast(c)
    是多余的;定义了
    fgetc
    函数
    int main()
    {
    
        //encodes a file using the (8,4) Hamming Code.
        //usage : HammingEncode.out < inputFile > outputFile 
            unsigned char const codebook[] = { 0x00, 0x1E, 0x2D, 0x33, 0x4B, 0x55, 0x66, 0x78, 0x87, 0x99, 0xAA, 0xB4, 0xCC, 0xD2, 0xE1, 0xFF };
            unsigned char in, nextByte;
            unsigned char const leftMask = 0xF0, rightMask = 0x0F;
            std::stringstream os;
    
            std::ios_base::sync_with_stdio(false);
            in = std::cin.get();
            while (std::cin) {
                nextByte = (in & leftMask) >> 4;
                os.put(codebook[nextByte]);
                nextByte = in & rightMask;
                os.put(codebook[nextByte]);
                in = std::cin.get();
            }
            std::cout << os.rdbuf();
    }
    
    int main()
    {
    
        //encodes a file using the (8,4) Hamming Code.
        //usage : HammingEncode.out < inputFile > outputFile 
        unsigned char const codebook[] = { 0x00, 0x1E, 0x2D, 0x33, 0x4B, 0x55, 0x66, 0x78, 0x87, 0x99, 0xAA, 0xB4, 0xCC, 0xD2, 0xE1, 0xFF };
        unsigned char in, nextByte;
        unsigned char const leftMask = 0xF0, rightMask = 0x0F;
        std::stringstream os;
    
        std::ios_base::sync_with_stdio(false);
    
    std::streambuf * pbuf = std::cin.rdbuf();
        do {
            in = pbuf->sgetc();
            nextByte = (in & leftMask) >> 4;
            os << codebook[nextByte];
            nextByte = in & rightMask;
            os << codebook[nextByte];
        } while (pbuf->snextc() != EOF);
        std::cout << os.rdbuf();
    }