Ticket #11112: 971-improve_ewma.patch

File 971-improve_ewma.patch, 3.0 KB (added by Viktar Palstsiuk <viktar.palstsiuk@…>, 4 years ago)
  • include/linux/average.h

    From af5568843594fb71055debe36e521fa8072fcecc Mon Sep 17 00:00:00 2001
    From: Bruno Randolf <br1@einfach.org>
    Date: Thu, 2 Dec 2010 19:50:37 +0900
    Subject: [PATCH] lib: Improve EWMA efficiency by using bitshifts
    
    Using bitshifts instead of division and multiplication should improve
    performance. That requires weight and factor to be powers of two, but i think
    this is something we can live with.
    
    Thanks to Peter Zijlstra for the improved formula!
    
    Signed-off-by: Bruno Randolf <br1@einfach.org>
    
    --
    
    v2:	use log2.h functions
    Signed-off-by: John W. Linville <linville@tuxdriver.com>
    ---
     include/linux/average.h |    4 +---
     lib/average.c           |   20 ++++++++++++--------
     2 files changed, 13 insertions(+), 11 deletions(-)
    
    diff --git a/include/linux/average.h b/include/linux/average.h
    index 7706e40..c6028fd 100644
    a b  
    11#ifndef _LINUX_AVERAGE_H 
    22#define _LINUX_AVERAGE_H 
    33 
    4 #include <linux/kernel.h> 
    5  
    64/* Exponentially weighted moving average (EWMA) */ 
    75 
    86/* For more documentation see lib/average.c */ 
    extern struct ewma *ewma_add(struct ewma *avg, unsigned long val); 
    2624 */ 
    2725static inline unsigned long ewma_read(const struct ewma *avg) 
    2826{ 
    29         return DIV_ROUND_CLOSEST(avg->internal, avg->factor); 
     27        return avg->internal >> avg->factor; 
    3028} 
    3129 
    3230#endif /* _LINUX_AVERAGE_H */ 
  • lib/average.c

    diff --git a/lib/average.c b/lib/average.c
    index f1d1b46..5576c28 100644
    a b  
    88#include <linux/module.h> 
    99#include <linux/average.h> 
    1010#include <linux/bug.h> 
     11#include <linux/log2.h> 
    1112 
    1213/** 
    1314 * DOC: Exponentially Weighted Moving Average (EWMA) 
     
    2425 * ewma_init() - Initialize EWMA parameters 
    2526 * @avg: Average structure 
    2627 * @factor: Factor to use for the scaled up internal value. The maximum value 
    27  *      of averages can be ULONG_MAX/(factor*weight). 
     28 *      of averages can be ULONG_MAX/(factor*weight). For performance reasons 
     29 *      factor has to be a power of 2. 
    2830 * @weight: Exponential weight, or decay rate. This defines how fast the 
    29  *      influence of older values decreases. Has to be bigger than 1. 
     31 *      influence of older values decreases. For performance reasons weight has 
     32 *      to be a power of 2. 
    3033 * 
    3134 * Initialize the EWMA parameters for a given struct ewma @avg. 
    3235 */ 
    3336void ewma_init(struct ewma *avg, unsigned long factor, unsigned long weight) 
    3437{ 
    35         WARN_ON(weight <= 1 || factor == 0); 
     38        WARN_ON(!is_power_of_2(weight) || !is_power_of_2(factor)); 
     39 
     40        avg->weight = ilog2(weight); 
     41        avg->factor = ilog2(factor); 
    3642        avg->internal = 0; 
    37         avg->weight = weight; 
    38         avg->factor = factor; 
    3943} 
    4044EXPORT_SYMBOL(ewma_init); 
    4145 
    EXPORT_SYMBOL(ewma_init); 
    4953struct ewma *ewma_add(struct ewma *avg, unsigned long val) 
    5054{ 
    5155        avg->internal = avg->internal  ? 
    52                 (((avg->internal * (avg->weight - 1)) + 
    53                         (val * avg->factor)) / avg->weight) : 
    54                 (val * avg->factor); 
     56                (((avg->internal << avg->weight) - avg->internal) + 
     57                        (val << avg->factor)) >> avg->weight : 
     58                (val << avg->factor); 
    5559        return avg; 
    5660} 
    5761EXPORT_SYMBOL(ewma_add);