bitmap标签bitmap标签

频道:银行理财 日期: 浏览:0

各位老铁们好,相信很多人对bitmap 标签都不是特别的了解,因此呢,今天就来为大家分享下关于bitmap 标签以及bitmap标签的问题知识,还望可以帮助大家,解决大家的一些困惑,下面一起来看看吧!

本文目录

安卓bitmap可以删除吗BitMap及其在ClickHouse中的应用Vc++:在标签控件中,标签页面是如何添加和创建的bitmap在CDP用户圈包中的应用安卓bitmap可以删除吗此方法返回一个删除了边距的剪切较小的Bitmap.首先将像素传递给int数组,然后使用数组比Bitmap.getPixel方法快一点

只需调用指示源位图和背景颜色的方法.

Bitmapbmp2=removeMargins(bmp,Color.WHITE);

privatestaticBitmapremoveMargins2(Bitmapbmp,intcolor){

//TODOAuto-generatedmethodstub

longdtMili=System.currentTimeMillis();

intMTop=0,MBot=0,MLeft=0,MRight=0;

booleanfound1=false,found2=false;

int[]bmpIn=newint[bmp.getWidth()*bmp.getHeight()];

int[][]bmpInt=newint[bmp.getWidth()][bmp.getHeight()];

bmp.getPixels(bmpIn,0,bmp.getWidth(),0,0,bmp.getWidth(),

bmp.getHeight());

for(intii=0,contX=0,contY=0;ii<bmpIn.length;ii++){

bmpInt[contX][contY]=bmpIn[ii];

contX++;

if(contX>=bmp.getWidth()){

contX=0;

contY++;

if(contY>=bmp.getHeight()){

break;

}

}

}

for(inthP=0;hP<bmpInt[0].length&&!found2;hP++){

//lookingforMTop

for(intwP=0;wP<bmpInt.length&&!found2;wP++){

if(bmpInt[wP][hP]!=color){

Log.e("MTop2","Pixelfound@"+hP);

MTop=hP;

found2=true;

break;

}

}

}

found2=false;

for(inthP=bmpInt[0].length-1;hP>=0&&!found2;hP--){

//lookingforMBot

for(intwP=0;wP<bmpInt.length&&!found2;wP++){

if(bmpInt[wP][hP]!=color){

Log.e("MBot2","Pixelfound@"+hP);

MBot=bmp.getHeight()-hP;

found2=true;

break;

}

}

}

found2=false;

for(intwP=0;wP<bmpInt.length&&!found2;wP++){

//lookingforMLeft

for(inthP=0;hP<bmpInt[0].length&&!found2;hP++){

if(bmpInt[wP][hP]!=color){

Log.e("MLeft2","Pixelfound@"+wP);

MLeft=wP;

found2=true;

break;

}

}

}

found2=false;

for(intwP=bmpInt.length-1;wP>=0&&!found2;wP--){

//lookingforMRight

for(inthP=0;hP<bmpInt[0].length&&!found2;hP++){

if(bmpInt[wP][hP]!=color){

Log.e("MRight2","Pixelfound@"+wP);

MRight=bmp.getWidth()-wP;

found2=true;

break;

}

}

}

found2=false;

intsizeY=bmp.getHeight()-MBot-MTop,sizeX=bmp.getWidth()

-MRight-MLeft;

Bitmapbmp2=Bitmap.createBitmap(bmp,MLeft,MTop,sizeX,sizeY);

dtMili=(System.currentTimeMillis()-dtMili);

Log.e("Margin2",

"Timeneeded"+dtMili+"mSec\nh:"+bmp.getWidth()+"w:"

+bmp.getHeight()+"\narrayx:"+bmpInt.length+"y:"

+bmpInt[0].length);

returnbmp2;

}

标签:android,bitmap

BitMap及其在ClickHouse中的应用问题要从面试或者大数据场景下最常见的一个算法说起,问题是这样的,假如有几十亿个unsignedint类型的数据,要求去重或者计算总共有多少不重复的数据?最简单的办法就是直接利用一个HashMap,进行去重。但是这里面有个内存使用量的问题,几十亿个元素,即使不考虑HashMap本身实现所用到的数据结果,单单key本身,假如每个unsignedint占用4个字节,简单算一下的话,这里都需要几十GB的内存占用,因此,这里就引出了BItMap。

BItMap的思想非常简单,就是用一个bit表示一个二元的状态,比如有或者没有,存在或者不存在,用bit本身的位置信息,对应不同的数据。比如针对上面的问题,我们可以开辟一个2^32bit的内存空间,每一个bit存储一个unsignedint类型的数据,有就是1,没有就是0,总共需要存储unsignedint类型的最大范围个数据,也就是2^32个数据,这个2^32其实就是所谓的基数。如下图所示:

假如存在数字8,那就把对应的第8位的值赋为1。上图插入的数据为1、3、7、8。接着依次把所有的数据遍历然后更新这个BitMap。这样我们就可以得到最终结果。

假如上面的问题变成了对几十亿个URL做判断,那应该怎么去做呢?URL没有办法和BitMap的位置关系对应上,所以,我们需要加一层哈希,把每个URL经过哈希运算得到一个整数,然后对应上BitMap。如下图所示:

但是有哈希,肯定会存在碰撞,如果BitMap基数(也就是长度)比较小,那碰撞的概率就大,如果基数比较大,那占用的空间又会比较多。BloomFilter的思想就是引入多个哈希函数来解决冲突的问题。也就是说对每个URL,经过多个哈希函数的运算,得到多个值,每个数值对应的BitMap的对应的位置都赋值为1。这个两个URL经过多个哈希函数结果还是一样的概率就大大降低。

但是由于依然存在冲突的可能性(其实冲突就是来源于我们BitMap的长度小于了数据量的基数,这也就是牺牲了准确性换来了空间使用的减少),所以BloomFilter存在假阳性的概率,不适用于任何要求100%准确率的场景,也就是说BloomFilter只能用来判无,不能用来判有。比如一个URL经过多次哈希运算之后,发现对应的BitMap的位置都已经是1了,那也不能说明,这个URL之前存在过了,也有可能是哈希冲突的结果。但是一个URL经过多次哈希运算之后,发现对应的BitMap的位置不是都是1,那当前URL之前一定是没有存在过的。

可以看到,BloomFilter引入多次哈希,在查询效率和插入效率不变的情况下,用较少空间的BitMap解决大数据量的判断问题。

大部分情况下仅仅做有无的判断是不能满足使用需求的,我们还是需要真正意义上的BitMap(可以方便的用来做交并等计算),但是最好可以在基数比较大的时候,依然可以占用相对比较小的空间。这就是RoaringBitMap所要实现的。

简单来说RoaringBitMap是BitMap的一种带索引的复杂BitMap数据结构。以32位的RoaringBitMap为例,首先划分2^16个空间(Container),每个Container内部都是一个大小为2^16bit的BitMap,总的内存使用量还是2^32=512Mb。这样的话和普通的BitMap是没有区别的,而RoaringBitMap的创新之处在于每个Container内的BitMap是在没有使用到的情况下是可以不分配内存空间的。这样可以大大减小内存的使用量。

(这个图片是RoaringBitmaps:ImplementationofanOptimizedSoftwareLibrary论文原图)

要将一个4个字节的数据插入RoaringBitMap,首先要用数据的高16位,找到对应的Container,然后用数据的低16在Container中插入。

在每个Container内部,RoaringBitMap不是简单的用BitMap来进行数据的存储,而是把Container的类型划分为几种,不同的Container用来存储不同情况的数据。

当2个字节(4个字节的原数据,低16位用来插入具体的Container中)的数据,总的个数小于4096个的时候,当前Container使用arrayContainer。为什么是4096个呢?4096*2B=8Kb,而一个Container如果是bitmap的结构的话,最多也就是2^16bit=8Kb的空间。所以这里当数据个数小于4096使用arrayContainer会更节省空间。当然这里名字为arrayContainer,实际上是链表结构,不需要最开始就初始化4096个shortint的数组。

当arrayContainer存储的数到4096个的时候(也就是使用内存到8Kb的时候),arrayContainer会转换为bitmapcontainer,bitmapcontainer就是一个2^16bit普通的bitmap,可以存储2^16=65536个数据。这个8Kb还有一个好处,是可以放到L1Cache中,加快计算。

这个严格的说,只是一种数据压缩存储方法的实现。其压缩原理是对于连续的数字只记录初始数字以及连续的长度,比如有一串数字12,13,14,15,16那么经过压缩后便只剩下12,5。从压缩原理我们也可以看出,这种算法对于数据的紧凑程度非常敏感,连续程度越高压缩率也越高。当然也可以实现其他的压缩方法。

RoaringBitMap其核心就在于加了一层索引,利用复杂的数据结构换取了空间上的效率。需要注意的是这里并没有增加计算的复杂度,其出色的数据结构让其在做交并计算的时候性能也毫不逊色。

ClickHouse中有bloom_filter类型的Skippingindexs,可以方便的用来过滤数据。

ClickHouse实现了大量的BitMap的函数,用来操作BitMap。ClickHouse中的BitMap在32位的时候用的是Set实现的,大于32位的时候也是使用RoaringBitMap实现的。我们这里不看具体的函数,我们来看一个典型的使用场景。

最常见的一个场景是根据标签来进行用户的圈选。常见的解决办法是有一张用户标签表,比如

要查询标签tag1='xx'和tag2='xx'的用户需要执行SQL:

但是由于不可能对每个tag列构建一级索引,所以这条SQL执行的效率并不高。可选的一种方式是先构建关于标签的BitMap数据结果,然后进行查询:

(1)创建tag的bitmap表:

(2)写入数据

(3)查询

如果有多张tag表,进行交并计算(要比普通的用户表进行JOIN或者IN计算要高效很多):

Vc++:在标签控件中,标签页面是如何添加和创建的给你段代码参考一下。这段是操作标签控件,以添加标签页。具体点哪个标签显示什么内容,还要在标签的消息响应函数中添加显示/隐藏页面的代码。

OnInitDialog()中进行初始化,代码如下:

CImageListimageList;

CBitmap bitmap;

bitmap.LoadBitmap(IDB_BMP_TABIMG);

imageList.Create(16,16,ILC_COLOR24|ILC_MASK,16,1);

imageList.Add(&bitmap,RGB(255,0,255));

//将控件子类化到控件类变量,就可以象进行类对象操作一样添加标签页

m_tabCtrl.SubclassDlgItem(IDC_TAB_CTRL,this);

m_tabCtrl.SetImageList(&imageList);

TC_ITEMTabCtrlItem;

TabCtrlItem.mask=TCIF_TEXT|TCIF_IMAGE;

TabCtrlItem.iImage=0;

TabCtrlItem.pszText="快捷面板";

m_tabCtrl.InsertItem(0,&TabCtrlItem);

m_pageShortcutBoard.Create(IDD_DLG_SHORTCUT,&m_tabCtrl);

CRectrc;

m_tabCtrl.GetClientRect(&rc);

m_pageShortcutBoard.SetWindowPos(NULL,12,28,rc.right-16,rc.bottom-40,SWP_SHOWWINDOW);

TabCtrlItem.mask=TCIF_TEXT|TCIF_IMAGE;

TabCtrlItem.iImage=1;

TabCtrlItem.pszText="位置记录";

m_tabCtrl.InsertItem(1,&TabCtrlItem);

m_pagePegRecord.Create(IDD_DLG_PEGRECORD,&m_tabCtrl);

m_pagePegRecord.SetWindowPos(NULL,4,28,rc.right-7,rc.bottom-32,SWP_HIDEWINDOW);

imageList.Detach();

bitmap.Detach();

//初始化结束

//选择标签的响应函数,在这里边决定显示哪个页面

voidCPaveShootDlg::OnTcnSelchangeTabCtrl(NMHDR*pNMHDR,LRESULT*pResult)

{

CRectrc;

m_tabCtrl.GetClientRect(&rc);

switch(m_tabCtrl.GetCurSel())

{

case0:

//显示这个页面

m_pageShortcutBoard.SetWindowPos(NULL,12,28,rc.right-16,rc.bottom-40,SWP_SHOWWINDOW);

//隐藏这个页面

m_pagePegRecord.SetWindowPos(NULL,4,28,rc.right-7,rc.bottom-32,SWP_HIDEWINDOW);

break;

case1:

//隐藏这个页面

m_pageShortcutBoard.SetWindowPos(NULL,12,28,rc.right-16,rc.bottom-40,SWP_HIDEWINDOW);

//显示这个页面

m_pagePegRecord.SetWindowPos(NULL,4,28,rc.right-7,rc.bottom-32,SWP_SHOWWINDOW);

break;

}

//*pResult=0;

}

bitmap在CDP用户圈包中的应用用户的标签数据一般存储在多张hive表中,在进行用户圈包,会涉及join的逻辑,限制了人群包数据的产出速度.使用标签进行用户分群,其本质还是集合之间的交、并、补运算。如果能够将符合每个标签取值的用户群提都提前构建出来,即构建好标签-用户的映射关系,在得到人群包的标签组合后直接选取对应的集合,通过集合之间的交/并/补运算即可得到最终的目标人群。bitmap是用于存储标签-用户的映射关系的比较理想的数据结构之一。ClickHouse目前也已经比较稳定的支持了bitmap数据结构,为基于bitmap的用户分群实现提供了基础。

整个方案主要包含以下几个技术问题:

hive提供了基础的row_number()over()函数,但是在操作亿级别行的数据时,会造成数据倾斜,受限于Hadoop集群单机节点的内存限制,无法成功运行。为此提出了一种针对亿级行大数据量的全局唯一连续数字ID生成方法。其核心思想如下:

具体的做法:由于亿级数据不支持全局row_number()排序,可考虑把一张大表按照一定的规则进行分拆,对每个子表打标签,然后分配id,对于第1个子数据集(M=1)的数据,其最终行号是1,2,3,4,…,N1;对于第2个子数据集(M=2)的数据,其最终行号是1+N1,2+N1,3+N1,4+N1,…,N2+N1....以此类推

DMP所有的画像数据最终汇总到了4张Hive表中,分别保存用户的基本信息(base表)、偏好信息(prefer表)、行为信息(action表)和设备信息(device表)。构建好join_id后,还需要将join_id关联到用户画像表中,产出构建bitmap所需要的bitmap_hive表。到此也就完成了Hive数据层的准备工作。

1.标签梳理

2.bitmap的构建和运算转换

具体的见原文档(非公有部分),注意边界值的处理(运算的转化)

这里的处理思想非常有意思https://cloud.tencent.com/developer/news/683175

3.Bitmap_CK表的设计

bitmap数据是通过Spark任务以序列化的方式写入到CH中的,为此我们再CH中创建了一个null引擎的表,bitmap的类型为string。然后以null引擎的表为基础创建了一个物化视图表,通过base64Decode()函数将String类型的bitmap转换成CH中的AggregateFunction(groupBitmap,UInt32)数据结构,最后以物化视图表为物理表,创建分布式表用于数据的查询。同时为了减少CH集群的处理压力,我们还进行了一个优化,即在null引擎表之前创建了一个buffer引擎的表,数据最先写入buffer引擎的表,积攒到一定的时间/批次后,数据会自动写入到null引擎的表。

4.Hive的关系型数据到CH的bitmap数据

Spark任务中,先通过sparkSQL将所需hive数据读取,保存在DataSet<Row>中。根据不同的标签类型设计的规则使用spark聚合算子进行运算。处理逻辑如下:

在这个过程中,我们还使用了bitmap的循环构建、spark任务调优、异常重试机制、bitmap构建后的数据验证等方法来提高任务的运行速度和稳定性。

5.bitmapSQL的生成

通过处理人群包的标签组合,确定所需要的bitmap以及这些bitmap之间的逻辑关系(下图红线标识),最终生成的bitmapSQL示例如下图所示。同时通过使用GLOBALIN代替比较耗时的GLOBALANYINNERJOIN,CHSQL运行效率也有了大幅度的提升。

对于Push消息类的服务需要通过接口获取人群中的数据用于消息发送。由于ClickHouse定位还是OLAP,不适合大量地在线调用,所以需要将人群的数据导入到Mongodb中来提供在线服务调用。为优化分页查询带来的性能问题,在导入Mongodb时为每个版本的每条数据生成一个自增的ID,同时对这个ID建立索引,在查询时根据页数计算出每一页数据的ID范围,然后再根据索引来查询数据,能保证千万级的分页查询平均响应时间在100ms以内。

一些对于bitmap的优化https://cloud.tencent.com/developer/news/680214

RoaringBitmap论文

https://arxiv.org/pdf/1402.6407.pdfhttps://arxiv.org/pdf/1603.06549.pdf

文章到此结束,如果本次分享的bitmap 标签和bitmap标签的问题解决了您的问题,那么我们由衷的感到高兴!

ibm

尘世美歌词

虚拟货币搭建

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 931614094@qq.com 举报,一经查实,本站将立刻删除。