代码之家  ›  专栏  ›  技术社区  ›  Nils Pipenbrinck

自适应IO优化问题

  •  1
  • Nils Pipenbrinck  · 技术社区  · 14 年前

    下面是一个有趣的优化问题,我想了好几天了:

    在系统中,我从一个慢IO设备读取数据。我不知道我需要多少数据。确切的长度只有在我读过整个包之后才知道(想想看,它有某种结束符号)。读取超过要求的数据不是问题,只是它在IO中浪费时间。

    两个约束也起作用:Reads是 非常 慢点。我读取的每个字节都要花费。而且,无论我读取的字节数是多少,每个读取请求都有一个固定的设置成本。这使得逐字节读取成本高昂。根据经验:安装成本大约与读取5字节的成本一样高。

    我读取的包通常在9到64字节之间,但很少出现较大或较小的包。整个范围将在1到120字节之间。

    当然,我知道一点我的数据:包的大小是一样的。我可以在这里将三种模式分类:

    具有相同大小的读取序列:

       A A A A A ...
    

    交替顺序:

      A B A B A B A B ...
    

    三胞胎的序列:

     A B C A B C A B C ...
    

    退化三元组的特殊情况也存在:

     A A B A A B A A B ...
    

    (A、B和C表示此处的某些包装尺寸介于1和120之间)。

    问题:

    根据前面包的大小,如何预测下一个读取请求的大小?我需要的东西适应快,使用很少的存储(比如说低于500字节),并且从计算的角度来看也是快速的。

    哦-而且预生成一些表是行不通的,因为读取大小的统计数据会因我从不同的设备读取而变化很大。

    有什么想法吗?

    3 回复  |  直到 14 年前
        1
  •  2
  •   Axn    14 年前

    您需要至少读取3个包,最多读取4个包才能识别模式。

    1. 阅读3个包裹。如果它们都一样大小,那么图案是AAAAAA。。。
    2. 如果它们的尺寸都不一样,请看第四个包裹。如果1=3&2=4,则模式为ABAB。否则,模式是ABCABC。。。

    有了这个大纲,对3个包大小(一次读取3*64字节)进行推测性读取可能是个好主意。

        2
  •  1
  •   ruslik    14 年前

    我看这里没什么问题。。但首先,有几个问题:

    1)是否可以异步读取输入(例如,独立线程、中断例程等)?

    2)你有一些可用的缓冲内存吗?

    3)如果您命令较长的读取时间,是否能够在读取整个数据包之前获取第一个字节?

    如果是这样的话(我认为在大多数情况下它是可以实现的),那么您就可以有一个单独的线程以尽可能高的速度读取它们并将它们存储在一个缓冲区中,当缓冲区满了时暂停,这样您的正常进程就可以使用一个同步的 getc() 在缓冲器上。

    编辑:我明白了。。是因为CRC还是加密?那么,您可以使用数据压缩的一些想法:

    考虑M个可能符号的N阶简单自适应算法:

    int freqs[M][M][M]; // [a][b][c] : occurences of outcome "c" when prev vals were "a" and "b"
    int prev[2];    // some history
    
    int predict(){
        int prediction = 0;
        for (i = 1; i < M; i++)
            if (freqs[prev[0]][prev[1]][i] > freqs[prev[0]][prev[1]][prediction])
            prediction = i;
        return prediction;
    };
    
    void add_outcome(int val){
        if (freqs[prev[0]][prev[1]][val]++ > DECAY_LIMIT){
            for (i = 0; i < M; i++)
                freqs[prev[0]][prev[1]][i] >>= 1;
        };
        pred[0] = pred[1];
        pred[1] = val;
    };
    

    freqs 必须是顺序数组 N+1 ,你必须记住 N 先前的价值观。 N个 DECAY_LIMIT 必须根据输入的统计数据进行调整。然而,即使它们可以被自适应(例如,如果它产生过多的未命中,那么衰减极限也可以被缩短)。

    最后一个问题是字母表。根据上下文的不同,如果有几个不同的大小,则可以创建到符号的一对一映射。如果更多,则可以使用量化来限制符号的数量。整个算法可以用指针算法编写,这样 N个 M 不会被硬编码。

        3
  •  1
  •   Mike Dunlavey    14 年前

    因为阅读速度太慢了,我想你可以给它一些CPU的能量,这样你就可以试着对阅读量做出一个有根据的猜测。

    这基本上是一个预测器,它有一个基于概率的模型。它将生成即将到来的消息大小和每个消息的成本的预测样本。然后选择具有最佳预期成本的邮件大小。

    然后,当您发现实际的消息大小时,使用Bayes规则更新模型概率,然后再次执行此操作。

    也许这听起来很复杂,但如果概率存储为定点分数,就不必处理浮点,因此可能不需要太多代码。我会用一些像 Metropolis-Hastings 算法作为我的基本模拟器和贝叶斯更新框架。(这只是一次初步的思考。)