精华内容
下载资源
问答
  • 而很早老师就教导我们:多次测量平均可以提高测量精度。那么精度到底是什么?多次平均到底能将精度提高多少倍,测量10次与测量100次平均得到的精度一样吗?测量10次求平均难度能将精度提高10倍? 从信号的角度来...

      测量,信号处理中的精度分析 误差传播理论

    我们测量得到的信号通常是叠加了噪声在里面,也就是说信号具有了一定的波动,或者说信号测量结果具有一定的不确定性,而对信号进行某些处理后,信号的波动会变成什么样呢?这通常可以用误差传播理论来解决:对于y=f(x),已知x的精度/波动大小,求y的精度/波动大小。比如采集N张照片取平均,能够把信噪比提升多少倍;拍多张照片合成提高图像质量,机器学习同时训练多种模型综合进行判断提高准确度。它一方面基于y与x的导数,另一方面,利用了:对同一个信号多次采样,信号本身是线性相关的,可以直接累加或相减,而噪声是相互独立正交的,因此总得噪声需要用平方和开根号。此外似乎还假设了噪声是正态分布的我对这个理论只是有一些了解,也不够深入,有一个目前还悬而未决的问题是,x是0均值标准差为σ的正太分布随机数/噪声,因此x的单次测量精度为σ,那么x的平方的单次测量精度是多少?(这个问题看似不能直接用这个误差传播理论计算,因为算出来是0,如果x的标准差不变,均值远离0,则还是可以使用这个公式的。如果不知道该用什么理论计算,可以参考另一篇博客,使用Matlab仿真一下就可以了,即用数值方法计算,而不是用符号计算

    此外,除了x的单次测量精度和N次测量精度可以计算,基于N个测量数据的标准差和方差的精度也有人进行了研究,见文献:Standard Errors of Mean, Variance, and Standard Deviation Estimators, Sangtae Ahn and Jeffrey A. Fessler, EECS Department, The University of Michigan, July 24, 2003

          误差无处不在,尤其是对于测量和加工。比如拿一把直尺测量一个圆的直径,用一个万用表测量一个电阻、电压的大小,加工一批零件的尺寸,可能会发现多个个体、多次测量的结果有一个微小的变动。而很早老师就教导我们:多次测量求平均可以提高测量精度。那么精度到底是什么?多次平均到底能将精度提高多少倍,测量10次与测量100次平均得到的精度一样吗?测量10次求平均难度能将精度提高10倍?

        从信号的角度来讲,那个微小的波动就是一种噪声,叠加在测量的信号之上。如图1,信号处理中常常用到均值滤波等方法来抑制噪声,某种程度上就利用了多次测量求平均提高精度的原理。

    图1

    在讨论精度之前,首先讨论统计学上对精度(precision)和准确度(accuracy)是怎么定义的。

    Precisionis about how close measurements are to one another.
    Accuracy is about how close measurements are to the ‘true answer’

    图2

    也就是说,精度是指多次测量的结果之间的相近程度,测量的重复性大小,可以用标准差来描述,标准差越大,那么测量结果之间的偏差也就越大。而准确度是指测量结果和“真实值”的相近程度。图2形象的展示了3种精度和准确度之间的联系,图中箭射中的位置即为测量值,而靶心是“真实值”。连续几次射中的位置越集中,说明精度越高(和距离靶心的距离无关),但是准确度却决定于射中位置和靶心的距离,可以考虑用平均的中心位置与靶心的距离来度量。

    因为测量总是存在误差,那么给出一个测量值的时候,往往也会给出它的误差范围:如X+Δx。比如你去买电阻,可能会有5%误差的,1%误差的,价格也就不一样。这个1%是相对误差,这是因为误差往往和测量对象的大小有关,测量值越大,往往能够容忍的误差就越大。对一个1kg和100kg的物体同样增加1g的重量,你的感知肯定是不一样的。加工一个1厘米和1米的零件,都要加工到1微米的表面精确度,难度不是一个数量级的。

    但是这个误差Δx定义往往比较模糊。它可以是X测量多次的标准差,也可以是标准差的两倍,三倍等,也可以是测量中的发现最大误差。测量误差往往符合正太分布,根据正太分布的3σ原则:

    数值分布在(μ-σ,μ+σ)中的概率为0.6826

    数值分布在(μ-2σ,μ+2σ)中的概率c为0.9544

    数值分布在(μ-3σ,μ+3σ)中的概率为0.9974

    可以认为,Y 的取值几乎全部集中在(μ-3σ,μ+3σ) 区间内,超出这个范围的可能性仅占不到0.3%。因此Δx定义为3σ可能是比较恰当的。实际使用的很可能是标准差。

    为了讨论的方便,这里的精度(也可以指误差、不确定性)统一指标准差,而实际的精度则可以直接乘以相应倍数即可。这相当于是对精度做了一个建模,那么接下来就可以用数学方法来对其进行运算和推导了。有一个理论叫误差传播理论(error propagation, erroranalysis),可以非常方便的对精度进行分析。

    首先看一个最简单的情况,如图3所示。

    A是测量对象,其精度已知(通过实验数据的标准差计算等等得来)。Z=f(A)是关于A的函数。当A有一个αA的波动(足够小)时,根据微积分的相关知识,可以得到Z的波动是

    比如A是黄金的重量,Z是黄金的价格,Z=100*A。标准品的重量10g,但是会有个别比10g略重或者略轻一点,那么实际的价格应该加上或者减去比例系数乘以波动的重量。

    基于此,那么对于更加复杂的函数应该怎么算呢?

    对于Z=f(x1,x2,x3,L,xn)

    完整的误差传播理论如下:

    注意这需要在x1,x2,x3,L,xn的误差随机并独立的情况下才成立,否则不能这样计算。也可以用下面的公式来进行一个大概判断,这不需要满足独立的条件:

        上面的误差传播公式在测量、信号、图像处理等领域中有比较广泛的应用。举个简单的例子,测量一块长方形地皮的面积,测量的长度为50米,误差为0.2米,测量的宽度为20米,误差为0.1米。假设长宽测量误差相互独立。显然,最终测量的面积为1000平方米,但该面积的测量误差是多少?

    这里Z=f(x1,x2)=x1*x2。x1和x2分别为长和宽。应用误差传播理论,面积的精度(误差)为:

    再回到最初的问题,假定单次测量的误差为Δx,测量N次取平均,平均之后的结果精度是多少?这里

    应用误差传播理论,最终误差为:

    可见,为了将精度提高一倍(误差减少为原来一半),必须至少测量4次取平均,而要将精度提高到原来的10倍,则至少需要测量100次取平均。

    参考文献:

    《Measurements and their Uncertainties A practical guide to modern error analysis》

    《An Introduction To Error Analysis The Study Of Uncertainties In Physical Measurements》

      Luchang Li

      2016.5.26

    展开全文
  • 对于分类问题,通常根据与分类器相关联...对于二元分类问题,所有这些性能测量都很容易获得。哪种衡量标准决于分类器的类型。硬分类器是非得分的,因为它们只产生结果。另一方面,软分类器是评分分类器,其产生...

    原文链接:http://tecdat.cn/?p=11160

    对于分类问题,通常根据与分类器关联的混淆矩阵来定义分类器性能。根据混淆矩阵 ,可以计算灵敏度(召回率),特异性和精度。 

    对于二进制分类问题,所有这些性能指标都很容易获得。  

    非得分分类器的数据

    为了展示多类别设置中非得分分类器的性能指标,让我们考虑观察到\(N = 100 \)的分类问题和观察到\(G = \ {1,\ ldots,5 \}的五个分类问题\):

    ref.labels <- c(rep("A", 45), rep("B" , 10), rep("C", 15), rep("D", 25), rep("E", 5))
    predictions <- c(rep("A", 35), rep("E", 5), rep("D", 5),
                     rep("B", 9), rep("D", 1),
                     rep("C", 7), rep("B", 5), rep("C", 3),
                     rep("D", 23), rep("C", 2),
                     rep("E", 1), rep("A", 2), rep("B", 2))
    df <- data.frame("Prediction" = predictions, "Reference" = ref.labels)

    准确性和加权准确性

    通常,将多类准确性定义为正确预测的平均数:

    其中\(I \)是指标函数,如果类匹配,则返回1,否则返回0。

    为了对各个类的性能更加敏感,我们可以为每个类分配权重\(w_k \),以使\(\ sum_ {k = 1} ^ {| G |} w_k = 1 \)。单个类别的\(w_k \)值越高,该类别的观测值对加权准确性的影响就越大。加权精度取决于:

    为了平均加权所有类,我们可以设置\(w_k = \ frac {1} {| G |} \,\ forall k \ in \ {1,\ ldots,G \} \)。注意,当使用除均等权重之外的任何其他值时,很难找到关于权重的特定组合的合理论证。

    计算精度和加权精度

    精度很容易计算:

    calculate.accuracy <- function(predictions, ref.labels) {
        return(length(which(predictions == ref.labels)) / length(ref.labels))
    }
    calculate.w.accuracy <- function(predictions, ref.labels, weights) {
        lvls <- levels(ref.labels)
        if (length(weights) != length(lvls)) {
            stop("Number of weights should agree with the number of classes.")
        }
        if (sum(weights) != 1) {
            stop("Weights do not sum to 1")
        }
        accs <- lapply(lvls, function(x) {
            idx <- which(ref.labels == x)
            return(calculate.accuracy(predictions[idx], ref.labels[idx]))
        })
        acc <- mean(unlist(accs))
        return(acc)
    }
    acc <- calculate.accuracy(df$Prediction, df$Reference)
    print(paste0("Accuracy is: ", round(acc, 2)))
    ## [1] "Accuracy is: 0.78"
    ## [1] "Weighted accuracy is: 0.69"

    F1分数的微观和宏观平均值

    微观平均值和宏观平均值表示在多类设置中解释混淆矩阵的两种方式。在这里,我们需要为每个类\(g_i \ in G = \ {1,\ ldots,K \} \)计算一个混淆矩阵,以使第\(i \)个混淆矩阵考虑类\(g_i \)作为肯定类,而所有其他类\(g_j \)作为\(j \ neq i \)作为否定类。 

    为了说明为什么增加真实负数会带来问题,请想象有10个类别,每个类别有10个观察值。然后,其中一个类别的混淆矩阵可能具有以下结构:

    预测/参考 1类 其他类
    1类 8 10
    其他类 2 80

    基于此矩阵,特异性将为\(\ frac {80} {80 + 10} = 88.9 \%\),尽管仅在18个实例中的8个实例中正确预测了1类(精度为44.4%)。 

    在下文中,我们将使用\(TP_i \),\(FP_i \)和\(FN_i \)分别在与第(i)个相关联的混淆矩阵中指示真阳性,假阳性和假阴性类。此外,让精度由\(P \)表示,并由\(R \)表示。

    计算R中的微观和宏观平均值

    在这里,我演示了如何在R中计算F1分数的微观平均值和宏观平均值。

     我们将使用 包中的  confusionMatrix 函数  caret来确定混淆矩阵:

    现在, 我们可以总结所有类的性能:

    metrics <- c("Precision", "Recall")
    print(cm[[1]]$byClass[, metrics])
    ##          Precision    Recall
    ## Class: A 0.9459459 0.7777778
    ## Class: B 0.5625000 0.9000000
    ## Class: C 0.8333333 0.6666667
    ## Class: D 0.7931034 0.9200000
    ## Class: E 0.1666667 0.2000000

    这些数据表明,总体而言,性能很高。但是,我们的假设分类器对于单个类别(如B类(精度)和E类(精度和查全率))的表现不佳。现在,我们将研究F1得分的微观平均值和宏观平均值如何受到模型预测的影响。

    微型平均F1的总体性能

     get.micro.f1 然后,该函数  简单地汇总计数并计算如上定义的F1分数。

    
    micro.f1 <- get.micro.f1(cm)
    print(paste0("Micro F1 is: ", round(micro.f1, 2)))
    ## [1] "Micro F1 is: 0.88"

     值为  0.88\(F_1 {\ rm {micro}} \)相当高,表明整体性能良好。 

    宏平均F1的类特定性能

    由于其中的每个混淆矩阵都  cm 已经存储了一对多的预测性能,因此我们只需要从其中一个矩阵中提取这些值,然后按上述定义计算\(F1 _ {\ rm {macro}} \):

    get.macro.f1 <- function(cm) {
        c <- cm[[1]]$byClass # a single matrix is sufficient
        re <- sum(c[, "Recall"]) / nrow(c)
        pr <- sum(c[, "Precision"]) / nrow(c)
        f1 <- 2 * ((re * pr) / (re + pr))
        return(f1)
    }
    macro.f1 <- get.macro.f1(cm)
    print(paste0("Macro F1 is: ", round(macro.f1, 2)))
    ## [1] "Macro F1 is: 0.68"

     值  0.68,\(F _ {\ RM {宏}} \)是断然比更小的微平均F1( 0.88)。 

    请注意,对于当前数据集,微观平均和宏观平均F1的总体(0.78)和加权精度(0.69)具有相似的关系。

    精确调用曲线和AUC

    ROC曲线下的面积(AUC)是评估软分类器分类分离质量的有用工具。在多类别设置中,我们可以根据它们对所有精度召回曲线的关系可视化多类别模型的性能。AUC也可以推广到多类别设置。

    一对一的精确召回曲线

     我们可以通过绘制\(K \)二进制分类器的性能来可视化多类模型的性能。

    该方法基于拟合\(K \)对所有分类器,其中在第(i)次迭代中,组(g_i \)设置为正类,而所有类((g_j \))与\(j \ neq i \)一起被视为否定类。请注意,此方法不应用于绘制常规ROC曲线(TPR与FPR),因为由于去二甲亚胺而产生的大量负面实例会导致FPR被低估。相反,应考虑精度和召回率:

    
    for (i in seq_along(levels(response))) {
    
      model <- NaiveBayes(binary.labels ~ ., data = iris.train[, -5])
      pred <- predict(model, iris.test[,-5], type='raw')
      score <- pred$posterior[, 'TRUE'] # posterior for  positive class
      test.labels <- iris.test$Species == cur.class
      pred <- prediction(score, test.labels)
      perf <- performance(pred, "prec", "rec")
      roc.x <- unlist(perf@x.values)
      roc.y <- unlist(perf@y.values)
      lines(roc.y ~ roc.x, col = colors[i], lwd = 2)
      # store AUC
      auc <- performance(pred, "auc")
      auc <- unlist(slot(auc, "y.values"))
      aucs[i] <- auc
    }
    

     

    print(paste0("Mean AUC under the precision-recall curve is: ", round(mean(aucs), 2)))
    ## [1] "Mean AUC under the precision-recall curve is: 0.97"

    该图表明  setosa  可以很好地预测,而    virginica  则更难预测。 平均AUC  0.97 表示该模型很好地分隔了三个类别。

    多类设置的AUC通用化

     单个决策值的广义AUC

     当单个数量允许分类时,可使用包装中的  multiclass.roc 功能  pROC确定AUC。  

    ## Multi-class area under the curve: 0.654

    函数的计算出的AUC只是所有成对类别比较中的平均值AUC。

     广义AUC 

    下面从Hand and Till,2001开始描述AUC的一般化  。

     

    似乎由于Hand and Till(2001),没有公开可用的AUC多类概括的实现。因此,我编写了一个实现。该函数  compute.A.conditional 确定\(\ hat {A}(i | j)\)。该  multiclass.auc 函数为所有具有\(i <j \)的类对计算\(\ hat {A}(i,j)\),然后计算结果值的平均值。输出为广义AUC \(M \),该属性  pair_AUCs 指示\(A(i,j)\)的值。

    
    
    multiclass.auc <- function(pred.matrix, ref.outcome) {
        labels <- colnames(pred.matrix)
    
        c <- length(labels)
        pairs <- unlist(lapply(combn(labels, 2, simplify = FALSE), function(x) paste(x, collapse = "/")))
    
        A.ij.joint <- sum(unlist(A.mean))
        M <- 2 / (c * (c-1)) * A.ij.joint 
        attr(M, "pair_AUCs") <- A.mean
        return(M)
    }
    model <- NaiveBayes(iris.train$Species ~ ., data = iris.train[, -5])
    pred <- predict(model, iris.test[,-5], type='raw')
    pred.matrix <- pred$posterior
    ref.outcome <- iris.test$Species
    M <- multiclass.auc(pred.matrix, ref.outcome)
    print(paste0("Generalized AUC is: ", round(as.numeric(M), 3)))
    ## [1] "Generalized AUC is: 0.988"
    print(attr(M, "pair_AUCs")) # pairwise AUCs
    ##    setosa/versicolor     setosa/virginica versicolor/virginica 
    ##            1.0000000            1.0000000            0.9627329

    使用这种方法,广义AUC为0.988 。生成的成对AUC的解释也相似。 

    摘要

    对于多类别问题 。

    • 对于硬分类器,您可以使用(加权)准确性以及微观或宏观平均F1分数。
    • 对于软分类器,您可以确定一对全精度召回曲线,也可以使用Hand and Till中的AUC 。
    展开全文
  • 延迟,吞吐和带宽

    千次阅读 2018-07-03 20:14:23
    关于系统领域的论文中...这个三个名词也经常用于Storage(disk, memory), network(Ethernet, RDMA) 和 software parts, 需多次测量取平均值。 Latency Latency is the time required to transmit a packet acro...

    关于系统领域的论文中经常出现Latency, Throughput 和 Bandwidth.这个三个名词也经常用于Storage(disk, memory), network(Ethernet, RDMA) 和 software parts, 需多次测量取平均值。

    Latency

    Latency is the time required to transmit a packet across a network.
    Latency may be measured in many different ways: round trip, one way, etc. Latency may be impacted by any element in the chain which is used to transmit data: workstation, WAN links, routers, local area network (LAN), server,… and ultimately it may be limited, in the case of very large networks, by the speed of light.

    Measuring network performance: TCP

    TCP is directly impacted by latency
    TCP is a more complex protocol as it integrates a mechanism which checks that all packets are correctly delivered. This mechanism is called acknowledgment: it consists of having the receiver transmit a specific packet or flag to the sender to confirm the proper reception of a packet.

    TCP Congestion Window
    For efficiency purposes, not all packets will be acknowledged one by one; the sender does not wait for each acknowledgment before sending new packets. Indeed, the number of packets that may be sent before receiving the corresponding acknowledgement packet is managed by a value called TCP congestion window.

    How the TCP congestion window impacts throughput
    If we make the hypothesis that no packet gets lost; the sender will send the first quota of packets (corresponding to the TCP congestion window) and when it will receive the acknowledgment packet, it will increase the TCP congestion window; progressively the number of packets that can be sent in a given period of time will increase (throughput). The delay before acknowledgment packets are received (= latency) will have an impact on how fast the TCP congestion window increases (hence the throughput).

    When latency is high, it means that the sender spends more time idle (not sending any new packets), which reduces how fast throughput grows.

    TCP中Latency可以理解为:send: The delay before acknowledgment packets are received (= latency)
    Throughput: the number of packets that can be sent in a given period of time

    Throughput

    单位时间内通过某个网络(信道,接口)实际数据量,可以理解为获得的实际带宽。显然吞吐量不会大于带宽或者额定速率,100Mbps的以太网,其吞吐量上限值也为100Mbps

    Throughput is defined as the quantity of data being sent/received by unit of time (MB/s)

    Bandwidth

    计算机网络中的主机在数字信道上,单位时间内从一端传送到另一端的最大数据量,即最大速率。(MB/s)

    write request to server repeatedly to get average write bandwidth.

    IOPS

    This means IO operations per second, which means the amount of read or write operations that could be done in one seconds time. A certain amount of IO operations will also give a certain throughput of Megabytes each second, so these two are related. A third factor is however involved: the size of each IO request. Depending on the operating system and the application/service that needs disk access it will issue a request to read or write a certain amount of data at the same time. This is called the IO size and could be for example 4 KB, 8 KB, 32 KB and so on.

    Average IO size x IOPS = Throughput in MB/s


    Reference:

    1.Measuring network performance: links between latency, throughput and packet loss
    2.计算机网络速率,带宽,吞吐量概念

    展开全文
  • 目前已经可以采集并存储数据,如何在采集5组数据后(每组数据100个),5组取平均,只存一组数量为100的数据
  • 关于TCP传输速率的测量方法

    万次阅读 2016-06-25 08:32:24
    人们非常关心下载速度,对于...TCP速率概述首先,TCP速率受到方面时延的影响,其中包括:1.本机以及对端机器的处理时延这部分指的是发送端和接收端主机由于操作系统调度,中断,网卡数据包调度等处理引入的时延,基
    人们非常关心下载速度,对于使用非包月宽带以及使用付费CDN的用户而言,这是典型的拿钱买时间的行为,我支付的费用越高,希望的下载速度越快,所使用的累积带宽越大。关于各种测速方法也是汗牛充栋了,本文介绍一下TCP传输的测速。

    TCP速率概述

    首先,TCP速率受到多方面时延的影响,其中包括:

    1.本机以及对端机器的处理时延

    这部分指的是发送端和接收端主机由于操作系统调度,中断,网卡数据包调度等处理引入的时延,基本属于操作系统的范畴,如果一个TCP数据包可以发送(窗口足够容纳),但是由于此时CPU被操作系统切换到了另外一个进程造成了延迟,或者说该数据包确实已经被发送了,但是由于网卡性能很低,需要将数据包的内容逐字节的拷贝,这也会引入额外的延迟,这部分时间就应该算到主机处理时延中。

    2.中间网络设备的处理时延

    这是中间设备的“主机处理时延”,与端主机的处理时延类似,所不同的是,这部分时延大多数是排队时延,相比较排队时延,路由器或者交换机的处理时延可以忽略,当前骨干
    网设备的pps线速都是超高的,如果你想优化那些设备的转发表,路由查找等逻辑,那是没找对地方,如今都是线卡硬件快速转发,交换网络处理都是纳秒级的,如果想优化路由转发等,那就去华为做光猫的部门谋份职位吧,那里会让你大展才华(绝非广告!)。再次重申,中间网络设备的处理时延主要是指排队时延。

    3.中间网络的传输时延

    这部分就不多说了,我们知道,光速很快,但也是有个值的,也就是说,光从一个地方到达另一个地方也是需要时间的,因此数据在载波中通过介质从一个主机到达另一个主机或者中间节点也是需要时间的,这部分时间就是网络传输时间,它主要受到串扰,折射率,光色散等物理因素的影响。
            知道了上述的因素,那么我们如果想测量一条TCP连接的数据传输速率,该怎么办呢?
            理论非常简单但却很苍白!总数据量除以时间。然而问题是,我在哪个层面上去测量速率,我需要什么样的精度。如果说我想知道我的主机的处理速率,那么时间就是指本机的处理时延,数据量就是在该时延内通过的数据量,更一般的,如果我想知道一个文件从一个WEB服务器上下载下来的速率,我就需要用总文件大小除以下载完成需要的时间,这部分时间包括上述三种时延的总和。
            这就涉及到了打点采样的问题了,本质上是两个问题,第一,在哪里开始打点采样,在哪里结束打点采样,第二,如何采样。

    应用层下载测速

    1.瞬时速度的移动指数平均

    打开浏览器,下载一个文件,各种下载工具或者浏览器自带的下载器上会显示一个下载速度以及剩余时间,这些值是怎么得到的呢?非常简单,下载工具或者浏览器本身也是一个应用程序,它可以在内部进行数据采样,比如固定间隔打点,然后统计这段间隔收到的数据量,二者相除得到速率,至于是剩余时间,一般通过协议获取,比如HTTP协议的响应中一般会有该信息,然后用剩余大小除以当前速率就是剩余时间。就是这么简单!
            问题是当前速率真的就是用固定采样间隔的数据量除以时间间隔这么简单吗?非也!事实上,大部分的下载工具以及浏览器使用的都是移动指数平均算法,据我所知,早期的IE没有使用该算法,而是使用瞬时采样值直接除以时间这种,你会看到用早期的IE下载文件,剩余时间的抖动特别大,一会儿是几分钟,一会儿就是几小时。
            公式我就不写了,挺麻烦的,一提到数学公式,懂的人不答理你,不懂的人说你装,也挺头大。

    2.平均速度的精确测量

    上面说的是瞬时速度的测量方法,如果想统计一次下载的平均速度呢?事实上更简单,这个统计由于是下载完成后做的,因此此时我已经有了足够的信息去计算这个平均速度,下载文件的总大小我是有的,总时间我可以通过HTTP协议统计出来,二者相除就是最终答案。
            一般而言,像HTTP协议这样的,响应头里都会有文件的大小字节数,应用程序收到这么多字节就结束打点采样,就能统计到下载这么多数据所使用的时间。这完全是像HTTP协议这样的应用层协议的功劳,它告诉了我足够的信息。
            在内核协议栈里面统计这些就难了!因为内核看到的只有一条TCP流,除非收到FIN,否则不知道什么时候会结束,也不会在一开始就知道后续数据的传输量...

    协议栈传输测速

    前段时间遇到一个需求,说是能不能在网卡层面统计到达某一个端口的流量,我说不能...我没有撒谎,即便能做到,我也不想做。

    1.瞬时速度的移动指数平均

    下载工具的瞬时速度是让人看的,人们更关注通过这个瞬时速度计算出来的剩余时间,让人们有个预期,好安排在一部电影下载完成之前是不是有时间去楼下便利店买几罐啤酒。TCP要这个速度有什么用呢?
            TCP协议栈层面的瞬时速度是指导TCP发送策略本身用的,我们知道TCP是一个把全世界都卷进来的反馈系统(把它看作全世界范围的受蝴蝶效应影响的混沌系统也行),它需要网络的反馈来指导它未来的行为。之前我曾经不厌其烦的说ACK时钟如何影响TCP对拥塞的感应等等,诚然那些并没有错,但是在本文中,我们上升一个层面,来看一下ACK所确认的数据量和RTT的共同作用。这个作用所反应的就是TCP传输速率。我们需要一个速率可以代表一个趋势,然后用这个趋势去指导TCP拥塞窗口的调整,这就需要平滑掉该速率的噪点,于是又一次我们遇到了移动指数平均!
            我们先看一下瞬时速度怎么测量。

            可以使用和用户态的方法一样的算法,固定间隔内统计收到的数据量,但是在协议栈,我们有更好的算法,这是因为我们可以借助于ACK。我们通过下图来描述算法:



    假设ACK匀速平滑到达,我们需要证明的是:

    这个证明是很容易的:

    证明了上面的等式后,我们同时也就有了计算瞬时速率的方法:
    1.任意取一点设为T1,获取当时发送出去但是尚未得到确认的数据量以及相关序列号

    2.在收到ACK的时候,记为T2,计算此ACK确认的数据量,用第一步的数据量减去本次确认的数据量

    3.每次收到ACK时迭代上述过程,做移动指数平均


    好了,我们通过ACK时钟流简单的搞定了瞬时速率值的计算。用这个可以指导很多事情,但不属于本文的范围。


    2.平均速率的精确测量

    上一节我们搞定了瞬时速度,但是由于做了移动指数平均平滑了噪点,所以我们丢失了部分信息,如果说我们需要一个精确的平均速度该怎么办呢?
            话说瞬时速度是指导连接内行为的,这个瞬时值的变化趋势可以在连接内被学习到,同时反作用于后续的速率调整,它反应了当前的网络状态以及该TCP连接对网络状态的反应,然而平均速率反应的是一种长期行为,比如我们可以通过对平均速率的分析了解链路的普遍状况等。这个平均值对于长期的机器学习行为更有统计上的意义。
    和应用层的平均速度测量一样,它比瞬时值的测量要更简单,但是我们要换一种思路,因为没有人事先告诉你有多少数据要下载。在TCP中,这个我们可以事后统计到,用FIN时的序列号减去连接初始时的序列号,就是发送的字节数。总的来讲,测试平均速度就是计算两个量,一个是数据总量,一个是时间总量,然而二者相除:




    请注意,分母是一个小段小段的时间加和,而不是直接取一个时间段,这是为什么呢?因为对于TCP而言,它有没有数据可发送是应用程序决定的,很多应用程序仅仅是保持一个TCP连接而已,然后在适当的时候传输一部分数据,这段中间的idle区间,是不应该算进传输时间的。现在的问题是如何算出各自的那一段段的数据量。我们一个一个来。
    首先,计算分子的加和是简单的,无非就是FIN的时候将序列号减去SYN-ACK时的初始序列号,难点在于分母的时间片加和。其实也不难,如果仅仅是理论分析,我想已经可以结束了,然而我们必须实现它的时候,难点就在于你对协议栈代码的理解深度了,如果熟悉代码,那也是三下五除二的事,但是不要走偏,不要让他人影响你的判断,很简单的事情很多人一讨论就无解了。我先给出答案:
    1).应用层数据进入TCP发送队列的时候判断
    如果此时队列长度为0,开始新一轮打点计时,否则什么都不做。
    2).ACK到来清除TCP发送队列的时候判断
    如果该ACK清空了发送队列,结束上一轮的计时,统计时间差,累加时间差。
    然后我们看一下代码如何实现,非常简单的不超过20行的代码,除却DEBUG信息,更少!代码如下:

    TCP客户端scocket创建的时候,初始化字段

    我在tcp_sock结构体中添加了几个字段,就不贴代码了,直接给出函数吧。
    struct sock *tcp_v4_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
                      struct request_sock *req,
                      struct dst_entry *dst)
    {
        ...
        inet_csk(newsk)->icsk_ext_hdr_len = 0;
    #if 1
        // 初始化时间片差字段
        newtp->vstamp = ktime_set(0, 0);
        // 初始化时间累加和字段
        newtp->pvstamp = ktime_set(0, 0);
        // 记录第一个序列号
        newtp->first_seq = newtp->snd_nxt;
    #ifdef REAL_TIME_DEBUG
        // 为了比较纯传输时间和连接时间的差异,引入一个字段记录连接时间开始
        newtp->first = 1;
        // 以下两个字段为了确认“入队/清空”的守恒
        newtp->pri1 = 0;
        newtp->pri2 = 0;
    #endif
    #endif
        ...
    }

    在数据进入发送队列的时候计时

    TCP数据统一通过skb_entail进入发送队列
    static void skb_entail(struct sock *sk, struct sk_buff *skb)
    {
            ...
            tcb->flags   = TCPCB_FLAG_ACK;
            tcb->sacked  = 0;
    #if 1
            // 如果发送队列为空,则开始新一轮计时
            if (tcp_write_queue_head(sk) == NULL) {
                    tp->vstamp = ktime_get_real();
    #ifdef REAL_TIME_DEBUG
                    tp->pri1 ++;
                    // 如果是首次发送数据,则记录时间
                    if (tp->first == 1) {
                            tp->bstamp = tp->vstamp;
                            tp->first = 0;
    #endif
                    }
            }
    #endif
            ...
    }

    在收到ACK的时候,检测发送队列是否已经清空

    TCP数据的ACK统一通过tcp_clean_rtx_queue进行清理
    static int tcp_clean_rtx_queue(struct sock *sk, int prior_fackets,
                       u32 prior_snd_una)
    {
        ...
        while ((skb = tcp_write_queue_head(sk)) && skb != tcp_send_head(sk)) {
            }               
    #if 1   
        // 如果队列已经清空,统计从第一个数据包入队到队列清空之间的时间差,并累加到计数器上。
        if (tcp_write_queue_head(sk) == NULL && tp->vstamp.tv64 != 0) {
            ktime_t delta = net_timedelta(tp->vstamp);
            tp->pvstamp = ktime_add(tp->pvstamp, delta);
            tp->vstamp = ktime_set(0, 0);
    #ifdef REAL_TIME_DEBUG
            tp->pri2++;
    #endif
        }         
    #endif
        ...
    }

    4.在TCP关闭连接的时候,输出结果

    我觉得目前这个东西没有什么用,所以只是简单printk出来看看即可,所以就不穿皮鞋了:
    void tcp_v4_destroy_sock(struct sock *sk)
    {
        struct tcp_sock *tp = tcp_sk(sk);
    #if 1
        struct inet_sock *inet = inet_sk(sk);
        u32 delta_seq = tp->snd_nxt - tp->first_seq - 1;
        // tsval是纯数据传输的用时
        struct timespec tsval = ktime_to_timespec(tp->pvstamp);
        // ttot则是TCP连接中从数据传输开始到连接结束的总用时
        struct timespec ttot = ktime_to_timespec(ktime_sub(ktime_get_real(), tp->bstamp));
    #ifdef REAL_TIME_DEBUG
        printk("saddr:%pI4 sport:%u  dport:%u   tot_byte:%#x  time:%lu %09lu  [%lu %09lu], %u %u\n",
                        &inet->saddr,
                        ntohs(inet->sport),
                        ntohs(inet->dport),
                        delta_seq,
                        (unsigned long)tsval.tv_sec,
                        (unsigned long)tsval.tv_nsec,
                        (unsigned long)ttot.tv_sec,
                        (unsigned long)ttot.tv_nsec,
                        tp->pri1,
                        tp->pri2);
    #endif
    #endif
    }

    好了,我们来看一下测试效果。

    测试

    如果你用curl,ab,wget去自己搭建的WEB服务器上下载一个文件:

    客户端:
    [root@localhost ~]# curl http://1.1.1.2/big10 >/dev/null
      % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                     Dload  Upload   Total   Spent    Left  Speed
    100 9765k  100 9765k    0     0  1210k      0  0:00:08  0:00:08 --:--:-- 1210k

    WEB服务器上dmesg信息:
    saddr:1.1.1.2 sport:80  dport:60463   tot_byte:0x989783  time:8 061474566  [8 062002622], 2 2
    可以看出,客户端统计的信息,服务端的连接时长,传输时长三者都是相同的,然而用浏览器下载这个big10试一下,我同样给出WEB服务器的dmesg输出:
    saddr:192.168.44.100 sport:80  dport:61023   tot_byte:0x9897bc  time:8 110491001  [15 156020871], 4 4
    为什么连接时间和数据传输时间会差这么多?我想这部分就是所谓的浏览器的动作所消耗的时间吧。为了确认一下,我修改了ab.c,在write_request函数之前加了个sleep(5)
    得到的结果跟浏览器访问的结果一样。为了用一种更加优雅的方式确认,我还特意请教了前公司的同事(WEB高手,高性能服务器专家,PHP高手,感兴趣的可以联系我),他告诉我一个很好用的测试方法:
    [root@localhost ~]# curl http://1.1.1.2/{big10,sleep.php,big10} >/dev/null
      % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                     Dload  Upload   Total   Spent    Left  Speed
    100 9765k  100 9765k    0     0  1214k      0  0:00:08  0:00:08 --:--:-- 1213k
      0     0    0     0    0     0      0      0 --:--:--  0:00:05 --:--:--     0
    100 9765k  100 9765k    0     0  1215k      0  0:00:08  0:00:08 --:--:-- 1213k

    命令中的sleep.php如下:
    <?php
    sleep(5);
    ?>
    服务端dmesg输出如下:
    saddr:1.1.1.2 sport:80  dport:53362   tot_byte:0x1312fb2  time:16 067200380  [21 069762118], 5 5
    可以看出连接时间正好比传输时间多了5s,这是一个可控的测试。事后我想让他再帮我写一个更猛的PHP,他就不理我了...估计是觉得太简单了吧,真是术业有专攻,隔行如隔山。

    写在最后

    够了,现在已经基本完成了本文,后面谁看到想用就用吧。很多事情需要你自己去思考,而不是大家一起讨论,讨论的前提是你已经有了哪怕是0.1版本,如果没有,讨论就是扯淡!
            虽然我比较喜欢数学,物理等理论性的东西,但我更喜欢show me the code,而不是document。你不懂,我不懂,他也不懂,大家在一起一唠嗑,大家就都懂了,这是鬼话。明确的说吧,以上写的东西都是大家讨论时被否掉的,但是事后冷静一想,不对呀,测试表明一切OK啊,到底谁错了,我不想让想法付之东流,就写了这篇...我不反对头脑风暴,但是更加认同专家型的头脑风暴,不然的话,大家都是满怀着激动的心,事事处处想挑战别人,见缝插针,我想这不是恶意,而是氛围所导致。
            本无意参与的人只是提一点小意见,结果就引发了所有人开始狂喷啊狂喷,毫无意义,毫无结果,理智在消退,胜利才是关键,只要有人提出一个方案,就会有人否定,什么都不对,什么都不妥,但是事实其实并没有这么恶劣。各国的领导人在记者招待会的表现我想大家都看到过,最佳的方式就是闭口不言,不然会被愤怒者扔鞋。在某种意义上,“挑战”是一个贬义词,它会扰乱你的思考,混淆你的视听,让你为了应对挑战举手投足而错乱,然后散会后,80%的人在整理好自己的思路后会发现自己并没有错。

            最后我想说几点关于规避挑战的问题,如果有人对你所述的细节不理解,那么就会有人追问,如果你面对他时没有气场,那你无疑会被引入他的思路,然后你就彻底乱了,大家都有过这样的经历,我试举出几例:
    1.面试的时候
    如果你再某方面你不是专家,就不要胡扯,不然被问起来会非常尴尬。面试官就在你面前,可能他也不懂,但是就是气场比你强,你怎么办呢?
    2.对待项目先斩后奏的时候
    我切身的体会,几年前我觉得领导的方法不对,我按着自己的想法做事,幸运的是,我成功了。但是成功的秘诀就是快速拿出你的1.0版本,而不是去跟他讨论方案。皇帝让将军开会讨论如何擒敌,将军逃避会议,并且不辞而别杳无音信,最好的办法就是,带敌将的头回来,一切都好说。
    3.被老婆查手机的时候
    也是我切身的体会。被查手机的时候,即便什么都没有发生,我依然觉得很慌张,这种神情被老婆看到,不断的挑战就开始了,其实我什么都没有做,但是回答起来还是略微的语无伦次,这是为什么?难道我错了吗?没有!关键在气场!气场不足,没错也变有错了,对方会说,没有问题你干嘛紧张!
    4.跟别人借钱的时候
    这个话题不多说,借一次钱你就明白了。
    最后的最后,现在是2016/06/25 07:53,我从凌晨3点多开始写这个,到了现在,中间有一些演算的过程,还拉了一脬屎。我为什这么早起来,其实我本来想5点半起床的,无奈昨晚女儿狂蹿我三脚,一脚在肚子,一脚在太阳穴,一脚在肋骨...我无法忍受,只能半夜爬起来写点东西了...爆炸!

    展开全文
  • 要求一:RSSI的测量值由对数路径损耗模型产生,为减小波动造成的误差,其值可由多次测量取平均值来得到。 要求二:对数路径损耗模型中的参考距离路径损耗和路径损耗因子可通过参考点相互之间的测量值估计。 要求三:...
  • 之前写过一篇HC04的使用文章,当时...虽然上一次也使用了多次测量取平均值,但是内有排除中间会有错误数据的情况。之前的程序是这样的(测距部分) :u32 t = 0; int i = 0; float lengthTemp = 0; floa...
  • 要求一:RSSI的测量值由对数路径损耗模型产生,为减小波动造成的误差,其值可由多次测量取平均值来得到。 要求二:对数路径损耗模型中的参考距离路径损耗和路径损耗因子可通过参考点相互之间的测量值估计。 要求三:...
  • matlab实现RSSI定位

    千次阅读 2020-07-04 15:55:26
    要求一:RSSI的测量值由对数路径损耗模型产生,为减小波动造成的误差,其值可由多次测量取平均值来得到。 要求二:对数路径损耗模型中的参考距离路径损耗和路径损耗因子可通过参考点相互之间的测量值估计。 要求三:...
  • 要求一:RSSI的测量值由对数路径损耗模型产生,为减小波动造成的误差,其值可由多次测量取平均值来得到。 要求二:定位指纹数据库的建立是基于网格形式产生不同的指纹节点。 要求三: 比较KNN算法与WKNN算法的CDF...
  • matlab实现RSSI指纹定位

    千次阅读 2020-07-04 15:48:33
    要求一:RSSI的测量值由对数路径损耗模型产生,为减小波动造成的误差,其值可由多次测量取平均值来得到。 要求二:定位指纹数据库的建立是基于网格形式产生不同的指纹节点。 要求三: 比较KNN算法与WKNN算法的CDF...
  • 要求一:RSSI的测量值由对数路径损耗模型产生,为减小波动造成的误差,其值可由多次测量取平均值来得到。 要求二:定位指纹数据库的建立是基于网格形式产生不同的指纹节点。 要求三: 比较KNN算法与WKNN算法的CDF...
  • 近红外光谱预处理方法及模型建立

    千次阅读 2020-07-04 10:31:23
    信号平滑是消除噪声最常用的一种方法,其基本假设是光谱含有的噪声为零均值随机白噪声,若多次测量取平均值可降低噪声提高信噪比。常用的信号平滑方法有移动平均平滑法和Savitzky-Golay卷积平滑法。 主要系数为窗口...
  • 就是我用的是f429挑战者的板子。用adc接地的时候发现有零点误差,于是就移植了网上一个f103的例程,通过多次测量求均值的方法来实现adc的精准测量。
  • OpenCV中提供了专门的计时函数...可以利用多次测量取平均值,具体代码如下:   double tTime; tTime = (double)getTickCount(); const int nTimes = 100; for(int i = 0; i &lt; nTimes; i++) { ...
  • 阻抗测量基础

    万次阅读 2017-08-31 12:56:00
    PCB的特性阻抗测量技术参考博文:PCB阻抗测量技术。)   一、阻抗测试基本概念 阻抗定义: 阻抗是元器件或电路对周期的交流信号的总的反作用。 AC 交流测试信号 (幅度和频率)。 包括实部和虚部。 图1 ...
  • 随着机器视觉应用的日益广泛,大幅面相机视觉系统的需求越来越,主要应用方向为大幅面高精度的定位与测量和场景拼接等。相机视觉系统的难点在于相机坐标系的统一,可以分为两类,一是相机视野间无重叠部分,...
  • TCP中RTT的测量和RTO的计算

    万次阅读 多人点赞 2012-06-11 10:27:22
    本文主要剖析:RTT的测量、RTO的计算 作者:zhangskd @ csdn   概述   RTO(Retransmission TimeOut)即重传超时时间。 TCP超时与重传中一个很最重要的部分是对一个给定连接的往返时间(RTT)的测量。由于...
  • 机器视觉HALCON-机器视觉标定和测量

    万次阅读 2018-03-30 16:17:28
    标定过程和测量过程,均需要保持摄像机与测量平面之间的距离固定,物品高度不能过高,否则影响测量结果。给出设计的中间过程和截图以及最终测量结果,并对测量结果进行误差计算和分析。二、总体...
  • 用Cobertura 测量测试覆盖率

    千次阅读 2007-09-17 10:48:00
    Cobertura 是一种开源工具,它通过检测基本的代码,并观察在测试包运行时执行了哪些代码和没有执行哪些代码,来测量测试覆盖率。除了找出未测试到的代码并发现 bug 外,Cobertura 还可以通过标记无用的、执行不到的...
  • 科学研究设计四:测量

    千次阅读 2017-11-17 22:25:28
    变量测量
  • 工程测量学学习 详细

    千次阅读 2020-05-23 17:50:38
    1.工程建设三阶段的主要测量工作(共同的?)怎么样理解不同工程测量工作的差异(特殊?)举例说明 在工程建设中,一般工程需要做的工作有:(1)工程规划设计,(2)工程施工建设(3)工程运营管理阶段; 在工程...
  • Eye Diagram眼图测量

    千次阅读 2018-04-03 11:23:18
    基本概念编辑什么是眼图“眼图就是象眼睛一样形状的图形。”眼图是用余辉方式累积叠加显示采集...[1] 由于眼图是用一张图形就完整地表征了串行信号的比特位信息,所以成为了衡量信号质量的最重要工具,眼图测量有时...
  • 大地测量学基础 (复习)

    千次阅读 多人点赞 2020-05-13 00:09:08
    这篇博文是用来复习课程“大地测量学基础”的,里面仅列出本人觉得这门课程比较重要的部分,希望能够帮助到有需要的朋友。 课本采用《大地测量学基础》孔祥元,武汉大学出版社。
  • OpenCV单目视觉定位(测量)系统(新增 含代码)

    万次阅读 多人点赞 2017-02-21 20:45:27
    OpenCV单目视觉定位(测量)系统,用于无人机视觉定位,视觉导航,机器人单目视觉定位
  • 工程测量的各种数据考点

    千次阅读 2019-05-19 18:25:00
    1. 平面控制网要能满足...竣工建筑物是主要建筑物,其碎部点的测量精度应提高到图根点的精度±5cm 用于测量地下管线的控制点,相对于邻近控制点,平面点位中误差和高程中误差不应大于50mm(5cm) 地下明显管线点的...
  • INA230测量电压电流功率

    千次阅读 2012-06-06 07:34:34
    INA320测量电压电流功率 INA320 可以测量电压电流功率 基本ADC功能 可以测试分流电阻的电流和VBUS的电压 工作电压2.7--5.5V 可以测量电压为0---28V 测量电流是VIN+ VIN-,测量电压是VBUS 对地的电压 VBUS...
  • 激光尺如何测量:逆向工程

    千次阅读 2020-09-25 10:14:20
    大多数激光卷尺使用相位而不是脉冲(飞行时间,TOF)距离测量方法。 为了本文的完整性,我将引用上一篇文章的部分理论: 在相位方法中,与脉冲方法相反,激光器始终工作,但是其辐射是由特定频率(通常是低于500 ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 23,117
精华内容 9,246
关键字:

多次测量取平均