范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文
国学影视

CountMinSketch计数器基于布隆过滤器思想的近似计数器

  简介
  CountMinSketch是一种计数器,用来统计一个元素的计数,它能够以一个非常小的空间统计大量元素的计数,同时保证高的性能及准确性。
  与布隆过滤器类似,由于它是基于概率的,因此它所统计的计数是有一定概率存在误差的,也就是可能会比真实的计数大。比如一个元素实际的计数是10,但是计算器的计算结果可能比10大。因此适合能够容忍计数存在一定误差的场景,比如社交网络中推文的访问次数。
  它一秒能够进行上百万次操作(主要取决于哈希函数的速度),并且如果我们每天有一个长度为100亿的数据流需要进行计数,计数值允许的误差范围是100,允许的错误率是0.1%,计数器大小是32位,只需要7.2GB内存,这完全可以单机进行计数。原理数据结构
  CountMinSketch计数器的数据结构是一个二维数组,每一个元素都是一个计数器,计数器可以使用一个数值类型进行表示,比如无符号int:
  增加计数
  每个元素会通过不同的哈希函数映射到每一行的某个位置,并增加对应位置上的计数:
  估算计数
  估算计数也是如上图流程,根据哈希映射到每一行的对应位置,然后读取所有行的计数,返回其中最小的一个。
  返回最小的一个是因为其他其他元素也可能会映射到自身所映射位置上面,导致计数比真实计数大,因此最小的一个计数最可能是真实计数:
  比如上图元素123映射到了元素abc第一行的相同位置,因此这个位置的计数累加了元素abc和元素123的计数和。但是只要我们取三行里面最小的一个计数,那么就能容忍这种情况。
  当然,如果一个元素的每一行的对应位置都被其他元素所映射,那么这个估算的计数就会比真实计数大。哈希函数
  CountMinSketch计数器里面的哈希函数需要是彼此独立且均匀分布(类似于哈希表的哈希函数),而且需要尽可能的快,比如murmur3就是一个很好的选择。
  CountMinSketch计数器的性能严重依赖于哈希函数的性能,而一般哈希函数的性能则依赖于输入串(一般为字节数组)的长度,因此为了提高CountMinSketch计数器的性能建议减少输入串的长度。
  下面是一个简单的性能测试,单位是字节,可以看到时间的消耗随着元素的增大基本是线性增长的:pkg: github.com/jiaxwu/gommon/counter/cm cpu: Intel(R) Core(TM) i5-10210U CPU @ 1.60GHz BenchmarkAddAndEstimate/1-8              2289142               505.9 ns/op         1.98 MB/s           0 B/op          0 allocs/op BenchmarkAddAndEstimate/2-8              2357380               513.7 ns/op         3.89 MB/s           0 B/op          0 allocs/op BenchmarkAddAndEstimate/4-8              2342382               496.9 ns/op         8.05 MB/s           0 B/op          0 allocs/op BenchmarkAddAndEstimate/8-8              2039792               499.7 ns/op        16.01 MB/s           0 B/op          0 allocs/op BenchmarkAddAndEstimate/16-8             2350281               526.8 ns/op        30.37 MB/s           0 B/op          0 allocs/op BenchmarkAddAndEstimate/32-8             2558060               444.3 ns/op        72.03 MB/s           0 B/op          0 allocs/op BenchmarkAddAndEstimate/64-8             2540272               459.5 ns/op       139.29 MB/s           0 B/op          0 allocs/op BenchmarkAddAndEstimate/128-8            1919720               538.6 ns/op       237.67 MB/s           0 B/op          0 allocs/op BenchmarkAddAndEstimate/256-8            1601738               720.6 ns/op       355.28 MB/s           0 B/op          0 allocs/op BenchmarkAddAndEstimate/512-8             950584              1599 ns/op         320.18 MB/s           0 B/op          0 allocs/op BenchmarkAddAndEstimate/1024-8            363592              3169 ns/op         323.17 MB/s           0 B/op          0 allocs/op BenchmarkAddAndEstimate/2048-8            187500              5888 ns/op         347.81 MB/s           0 B/op          0 allocs/op BenchmarkAddAndEstimate/4096-8            130425              8825 ns/op         464.15 MB/s           0 B/op          0 allocs/op BenchmarkAddAndEstimate/8192-8             67198             17460 ns/op         469.18 MB/s           0 B/op          0 allocs/op 复制代码数组大小、哈希函数数量、错误范围、错误率
  数组大小、哈希函数数量、错误范围和错误率之间是互相影响的,如果我们想减少错误率和错误范围,则需要更大的数组和更多的哈希函数。但是我们很难直观地计算出这些参数,还好有两个公式可以帮助我们计算出准确的数值:
  在我们可以确定我们的数据流大小和能够容忍的错误范围和错误率的情况下,我们可以根据下面公式计算数组大小和哈希函数数量:n = 数据流大小  m = 数组大小 k = 哈希函数数量  eRange = 错误范围(ErrorRange) eRate = 错误率(ErrorRate) ceil() = 向上取整操作 E = 2.718281828459045(自然常数)  m = ceil(E/(eRange/n)) k = ceil(ln(1/eRate)) 复制代码应用TopK(海量数据计数器)
  对于海量数据流中频率最高的K个数,如果使用常规的map,由于内存大小限制,一般情况下单机无法完成计算,需要把数据路由到多台机器上进行计数。
  而如果我们使用CountMinSketch则能够在单机情况下处理大量的数据,比如开头所提到对于一个长度为100亿的数据流进行计数,只需要7.2GB内存。这个计数结果可能存在一定误差,不过我们可以在这个基础上再进行过滤。TinyLFU
  TinyLFU是一个缓存淘汰策略,它里面有LFU策略的思想,LFU是一个基于访问频率的淘汰策略,因此需要统计每个元素被访问的次数。如果对每个元素使用一个独立的计数器,那么这个成本会很大,而且对于一个缓存淘汰策略来说,我们并不需要这个计数器非常大且非常准确。
  因此TinyLFU使用一个计数器长度为4位的CountMinSketch计数器统计每个元素的频率,减少计数所消耗的内存空间,同时还引入了计数衰减机制避免某些之前热门但是当前已经很少被访问的元素很难被淘汰。实现
  这里给出一个Golang的泛型实现,这个实现支持uint8、uint16、uint32、uint64等基本类型计数器,实际上还可以实现比如长度为2bit、4bit、6bit的计数器,但是代码会稍微复杂一点(特别是非2的次方的计数器)。
  代码地址数据结构
  这里的数据结构核心是一个k*m的二维数组counters,k是哈希函数数量,m是数组每一行的长度;countersLen其实就是m;hashs是哈希函数列表;maxCount是当前类型的最大值,比如uint8就是255,下面的计算需要用到它。type Counter[T constraints.Unsigned] struct { 	counters    [][]T 	countersLen uint64       // 计数器长度 	hashs       []*hash.Hash // 哈希函数列表 	maxCount    T            // 最大计数值 } 复制代码初始化
  我们首先使用上面提到的两个公式计算数组每一行长度和哈希函数的数量,然后初始化哈希函数列表和二维数组。// 创建一个计数器 // size:数据流大小 // errorRange:计数值误差范围(会超过真实计数值) // errorRate:错误率 func New[T constraints.Unsigned](size uint64, errorRange T, errorRate float64) *Counter[T] { 	// 计数器长度 	countersLen := uint64(math.Ceil(math.E / (float64(errorRange) / float64(size)))) 	// 哈希个数 	hashsCnt := int(math.Ceil(math.Log(1.0 / errorRate))) 	hashs := make([]*hash.Hash, hashsCnt) 	counters := make([][]T, hashsCnt) 	for i := 0; i < hashsCnt; i++ { 		hashs[i] = hash.New() 		counters[i] = make([]T, countersLen) 	} 	return &Counter[T]{ 		counters:    counters, 		countersLen: countersLen, 		hashs:       hashs, 		maxCount:    T(0) - 1, 	} } 复制代码增加计数
  对于一个元素,我们需要把它根据每个哈希函数计算出它在每一行数组的位置,然后增加对应位置计数器的计数值。
  这里需要注意的是,计数值可能会溢出,因此我们首先判断是否溢出,如果溢出则设置为最大值。// 增加元素的计数 func (c *Counter[T]) Add(b []byte, val T) { 	for i, h := range c.hashs { 		index := h.Sum64(b) % c.countersLen 		if c.counters[i][index]+val <= c.counters[i][index] { 			c.counters[i][index] = c.maxCount 		} else { 			c.counters[i][index] += val 		} 	} } 复制代码估算计数
  同增加计数原理,把元素根据哈希函数映射到每一行数组的对应位置,然后选择所有行中最小的那个计数值。// 估算元素的计数 func (c *Counter[T]) Estimate(b []byte) T { 	minCount := c.maxCount 	for i, h := range c.hashs { 		index := h.Sum64(b) % c.countersLen 		count := c.counters[i][index] 		if count == 0 { 			return 0 		} 		minCount = mmath.Min(minCount, count) 	} 	return minCount }
  作者:jiaxwu
  链接:https://juejin.cn/post/7142896490061496334
  来源:稀土掘金
  著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

今天是泸州的生日,酒城四十正当红,希望更加勇往直前为什么标题说今天是泸州的生日呢?因为1983年的3月3日,国务院批准成立省辖泸州市。结束了23年县级市限制发展的难过岁月。虽然对泸州这座古城而言,只是它历史发展的一个阶段而已,接近唐哀帝李柷李柷,本名李祚,京兆长安(今陕西西安)人,为唐王朝第21任皇帝,亦为末代皇帝,是唐昭宗李晔的第9子。唐昭宗景福元年(壬子,892年)九月初三,李祚出生长安宫廷之内。唐昭宗乾宁四年(揭秘古人睡的硬枕头,真的会不会硌得慌?阅读之前,麻烦您点一个关注,既方便您进行讨论与分享,又能给您带来不一样的参与感,感谢您的支持!古人曾说高枕无忧,在现代人看来是相当费解的,因为大家看到古人睡的高枕头第一反应大多是不私域流量运营激发链条潜能,变单链条为可循环多链条从原始的会员运营模式,逐步发展到全私域流量运营,如何在当中激发链条潜能,从单链条变为可循环的多链条?作者以婴幼儿奶粉行业为例,结合自己过去的经验,分享构建循环型私域流量全链路运营体ChatGPT会成为机械公敌吗?一台机器到底能不能具备人类智能?这是从人工智能诞生开始,人们就在争论不休的问题。人工智能之父图灵给出了一个有信服力的测试方法。假设一个人通过远程聊天的方式,与对方进行一系列的问答,最新!长江存储获得490亿元投资!据南华早报报道,中国最大的存储芯片制造商长江存储获得大基金等投资者490亿元人民币注资。这笔投资使YMTC的注册资本翻了一番,超过1050亿元。去年被列入美国贸易黑名单的中国头部存今年38购物节,正式开始38购物节来了今年第一波大促38购物节,已经悄悄开始了。从2月中旬开始,淘宝天猫京东快手抖音已经开始了38购物节的招商活动和相关布局。随着主力玩家的入局,今年的第一场电商大战正式拉阿里巴巴王坚院士当选全国政协委员曾多次提出云计算是数字经济的基础每经记者陈婷每经编辑刘雪梅3月3日消息,每日经济新闻记者从有关方面获悉,中国工程院院士阿里巴巴集团技术委员会主席王坚当选第十四届全国政协委员。王坚院士本次带来的提案,涉及中小企业数当下社会的财富第3次分配到底是指什么呢?当前社会的财富第三次分配通常指的是数字化信息化和智能化等新技术所带来的经济变革。在这一变革中,由于新技术的出现和应用,创造了新的生产力和生产方式,进一步加快了经济的发展和转型。这也P50EP50Pro最新版本更新P50E版本3。0。0。205合入2月安全补丁。新版本来了,快去看看P50EHarmonyOS3版本3。0。0。205。本次更新优化了应用预置方式。适配机型C版本号为C00的以下机沈向洋履新!这位AI顶咖曾是微软首位中国高管近日,香港科技大学正式发布公告称,沈向洋教授将于3月6日接替现任校董会主席廖长城,成为港科大的新任校董会主席,为期3年。出任港科大校董会主席沈教授早在2000年便和港科大结下了渊源
priest杀破狼摘读1。世间所有仇与怨的消弭,大抵一边靠忘,一边靠将心比心吧。2。我相信只要你愿意,世上没有任何东西能打败你,包括这副皮囊。3。他毕生所求,不过家国安定而已。若可战,便披甲上马,若需守福建省诏安县劳模协会参观乡村振兴成果,盛赞乡村新面貌中国经济周刊经济网讯9月20日至10月14日,福建省诏安县劳模协会先后三次,组织全县劳模到沿海平原山区,参观诏安县各级党委政府贯彻落实党中央关于乡村振兴的发展战略的成果。各乡镇村坚党建带团建湖南外贸职业学院宣传学习党的二十大精神红网时刻新闻10月27日讯(通讯员吴丹刘彦)10月25日,湖南外贸职业学院国际商务学院教师支部和国贸2201班团支部共同开展了党建带团建,奋进新征程主题党日活动,该校党委书记唐瑾全不是德系车不好而是中国制造太强了,引领行业创新红旗HQ9成功了毋庸置疑,几乎所有消费产品,都有品牌的高低贵贱之分,即使L使用编织袋图案,那也是L的编织袋。在汽车领域就更是如此了。在人们的传统观念中,德系的奔驰宝马奥迪,日系的雷克萨斯讴歌英菲尼北交所公布第三季度证券公司执业质量评价结果,申万宏源居首大河财立方消息10月27日,北交所消息,北交所全国股转公司根据北京证券交易所全国中小企业股份转让系统证券公司执业质量评价细则,对证券公司2022年第三季度的执业质量情况进行了评价,系统OriginOS3。0来了蓝厂新系统官宣11。8发布今天上午,vivo官宣将于11月8日11月9日举行2022开发者大会。官方还公布了为期两天的开发者大会具体安排。其中11月8日的主会场赫然写着新系统的发布时间,当天下午145015深圳瑞捷2022年前三季度净利润1432。59万元同比下降84。88中证智能财讯深圳瑞捷(300977)10月27日披露2022年第三季度报告。2022年前三季度,公司实现营业总收入4。20亿元,同比下降22。42归母净利润1432。59万元,同比上了年纪后,喝点酒也正常,但是这3件事千万别做,容易讨人嫌导语上了年纪后,喝点酒也正常,但是这3件事千万别做,容易讨人嫌很多人在上了年纪之后,就会特别的馋酒,偶尔身边的朋友就会在老酒友身边唠叨酒有什么好喝的,年纪大了还是少喝点,很多酒友虽寒风呼啸中的创始人们内心极度挣扎作为浩浩荡荡创业大军中的所谓创始人,我们曾经都那么意气风发,那么舍我其谁,那么无所畏惧。然而,这个世界从来都不是勇气与魄力就可以打倒一切。看热闹的从来都不嫌事儿多,但是处于漩涡中的经典游戏魂斗罗现实中的原型,卑劣的名声让美国总统下不来台前言有这么一个游戏系列,2D都不错,3D化之后骂声一片,如今该系列完全就是在吃老本,可就是有那么一群像我们一样的老玩家为之动容。这个系列便是曾经的魂斗罗。毫不夸张地讲关于魂斗罗,多寂静岭新作公开!可惜不是自己做的日本知名游戏公司KONAMI(科乐美)在发布会上,公布了寂静岭系列的最新动态。1寂静岭2重制,使用的是虚幻5引擎!登陆PS5和PC平台。其中PS5主机独占一年,商店页面现在已经开放