cvDFT的性能问题

最近写一个代码的时候,发现cvDFT在32位下比64位下速度还快,觉得很不可思议。于是查看了OpenCV的源代码,发现了如下的说明:

//On Win64 optimized versions of DFT and DCT fail the tests (fixed in VS2010)

看来是VS2008在优化的时候会让OpenCV的DFT和DCT出错,不得已禁用了编译器代码优化,从而速度较慢。

唉~看来毕业的时候得用VS2010了~

OpenCV 2.4.2 imdecode/cvDecodeImage 的 BUG及解决方案

OpenCV是很好用的开源库,不过,还是有一些BUG的~

比如,今天遇到的问题是,imdecode的执行速度很慢。

照理来说,imdecode是从内存解析一幅图像,应该比cvLoadImage还快(或者至少不慢)。

但实际上,执行的时候却是imdecode慢很多(一张图片要1秒以上)。而且很奇怪的是,在某些机器很快,某些机器就很慢。而且调用了不同版本的OpenCV速度也不同。

为什么呢?本着质疑的原则,开始查看OpenCV的源代码。

imdecode的实现在modules\highgui\src\loadsave.cpp中。结果,发现opencv也是先将内存数据写到文件然后再读取的……这不是偷懒么orz

不过,逻辑上没有问题,算法上却犯二了……OpenCV2.4.2及之前版本在实现这个函数的时候,申请了一个临时文件(C:\user\用户名\AppData\Local\Temp\下的ocvXXXX.tmp文件,其中XXXX是0~F的16进制数)。然后写这个文件,然后读。关键是,没有删除!原因是因为临时文件可能不存在(本意是如果形如ocvXXXX.tmp的文件都存在了,那么就不能再新建了,所以返回空不作操作,实际上不会走到这一步),所以最后不一定需要删除文件。于是写OpenCV的小朋友这里为了程序稳定就没有删除临时文件。如图所示:

temp2

结果就是:如果调用imdecode次数越多,速度越慢。超过65535次则每次需要枚举65535个临时文件是否存在。。这个时间对系统而言大致是1秒吧~

当然,写OpenCV的小朋友还是意识到了这个问题,至少2.4.5开始这部分代码就改成判断临时文件名是否为空,不为空则删除了。这样就不会产生临时文件堆积的问题了~

 

anyway,结论就是:

如果想从内存里面直接解析一幅图像,还是乖乖自己写到文件再读取吧~可以模仿opencv去向系统申请临时文件的说~(GetTempPathA和GetTempFileNameA函数)

那些戏剧性的事情~

1)高一暑假学游泳,属于刚刚能游50米的那种;然后高二开学学校举行游泳比赛,因为班级成员人数不足被拉去凑数(4×50接力)。。结果,一共就4个班凑齐了4个人游接力。因为我游得最慢,所以虽然我们班其它三个人速度不错,但是还是屈居第二。结果,戏剧性的一幕出现了,第一名的队伍被判犯规(好像是说中途碰到了泳池壁),被取消成绩,于是我们就成为了第一名……所以,我还是获得过游泳比赛冠军的:)虽然现在扔进水里就会被淹死了吧= =

2)高一参加科技节的凝胶滴定实验(生物),就是老师示范一遍,大家模仿一遍,看谁的实验结果最好看……按照班级顺序进行比赛的,所以到我们班(10班,最后一个)。其实大家都做得差不多。然后老师打分,结果好多都同分。这时候学生会的人就要老师给出一二三名,老师看了看评分表,然后看了看我们(只剩我们刚做完实验还没回班级),就说,那就他们第一吧:) 于是,就这么拿到了这个比赛的第一名= = 后来,班主任还让我用这个第一名去申请学校科技新苗,我觉得比较rp,所以就没申。

finding a job

目前找工作的公司及相关进展:

阿里:笔试(因为试卷原因没印出来)->面试*2->offer
微软:笔试->挂
google:机试*2(第一次被判抄袭orz)->面试*1->面试*2->面试*2->挂
腾讯:电面*2->笔试->面试*2->offer
百度:笔试->面试*3->offer
联想:面试(没去面,因为人在上海)
虹软:笔试->面试->等消息
爱奇艺:笔试->面试(两次让去面试都有事情冲突……)
雅虎北研:笔试->面试*3->面试(技术总监)->等消息
网易有道:笔试(因为要先听宣讲会,而宣讲会人满了只能在外面等,于是直接翘了)
hulu:笔试->挂
微策略:笔试->面试*2->终面->offer
创新工厂:笔试->挂

目前已挂:微软、hulu、创新工程、google
目前已翘:联想、爱奇艺、网易有道
目前已拒:阿里、微策略、百度、雅虎北研
目前等消息:虹软(目测皆挂)
目前已签:腾讯
last update:20131220

test for code


class Solution {
public:
struct info
{
int id;
int step;
};
void gen(vector &vstr,vector *c, int id,vector> &res)
{
vector v;
vector> tres;
if(c[id].size()==0)
{
v.push_back(vstr[id]);
res.push_back(v);
return;
}
int i,j;
for(i=0;i> findLadders(string start, string end, unordered_set &dict) {
// Start typing your C/C++ solution below
// DO NOT write int main() function
vector> res;
vector v;
if(start==end) //start is end
{
v.push_back(start);
res.push_back(v);
return res;
}
unordered_map mp;
unordered_map::iterator iter_m;
unordered_set::iterator iter_s;
vector vstr;
dict.insert(start);
dict.insert(end);
int id=0,i,j,k;
for(iter_s=dict.begin();iter_s!=dict.end();++iter_s)
{
vstr.push_back(*iter_s);
mp.insert(make_pair(*iter_s,id));
id++;
}
int nStart, nEnd;
iter_m = mp.find(start);
nStart = iter_m->second;
iter_m = mp.find(end);
nEnd = iter_m->second;

int len = start.length();
int nTotal = mp.size();
vector *c = new vector [nTotal];
int *step = new int [nTotal];
for(i=0;i q;
q.push(temp);
while(!q.empty())
{
cur=q.front();
q.pop();
if(cur.step>=nMin) continue;
string str = vstr[cur.id];
for(i=0;isecond;
if(step[id]<=cur.step) continue; if(step[id]!=cur.step+1) { temp.id=id; temp.step=cur.step+1; q.push(temp); step[id]=cur.step+1; if(id==nEnd) nMin = cur.step+1; //find end } c[id].push_back(cur.id); } } } if(c[nEnd].size()==0) //no result { delete[]c; delete[]step; return res; } gen(vstr,c,nEnd,res); delete[]c; delete[]step; return res; } };

home hot home

魔都真热!

话说最近魔都连着4天40℃+,于是今天的39.6℃就显得不那么热了。到底有多热呢?下面举两个小例子:
1)回家当然就要舒舒服服洗个热水澡啦~于是打开龙头,咦,热水器这么快就热了?虽然温度比往年差了点,年久了老化了吧:)于是洗了一分钟不到,突然被烫了……原来刚才那是常温的水,后来才是真的热水啊~
2)晚上发现有点起风了,于是很happy的跑到阳台上去吹风,结果:阵阵热浪扑面而来,这感觉就跟站在空调外机外面吹一样。要不要这么热啊!都已经晚上了诶!

anyway,看来得7×24小时空调了……往年那个37度不开空调盖被子睡觉的少年啊,你现在怎么就成了35度就热坏了的死胖子了呢!

不过,home sweet home,最后的暑假开始了。。第0x00天

汉明距离的快速计算方法

首先,所谓汉明距离,是说两个01串之间不相同的0和1的个数。
比如: 1 1 0 1 1 和 1 0 1 0 1 的汉明距离就是3(中间三位不相同)
那么,怎么快速计算汉明距离呢?
这里给出三个方法,均以两个unsigned __int64的数a和b的汉明距离来做例子:

1)参考文章:http://crane.is-programmer.com/posts/17830.html

unsigned __int64 nHammingDist=a^b;

nHammingDist = (nHammingDist & 0x5555555555555555UI64) + ((nHammingDist>>1) & 0x5555555555555555UI64);
nHammingDist = (nHammingDist & 0x3333333333333333UI64) + ((nHammingDist>>2) & 0x3333333333333333UI64);
nHammingDist = (nHammingDist & 0x0f0f0f0f0f0f0f0fUI64) + ((nHammingDist>>4) & 0x0f0f0f0f0f0f0f0fUI64);
nHammingDist = (nHammingDist & 0x00ff00ff00ff00ffUI64) + ((nHammingDist>>8) & 0x00ff00ff00ff00ffUI64);
nHammingDist = (nHammingDist & 0x0000ffff0000ffffUI64) + ((nHammingDist>>16) & 0x0000ffff0000ffffUI64);
nHammingDist = (nHammingDist & 0x00000000ffffffffUI64) + ((nHammingDist>>32) & 0x00000000ffffffffUI64);

2)如果上述汉明距离需要频繁计算,那么,打表法不失为一种好方法。考虑到打表的大小要尽可能贴近L1缓存限制,所以考虑8bit计算一次:

static int Ham_count[256]={0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8};

unsigned __int64 temp=a^b;
uchar *uch=(uchar*)&temp;
int i,nHammingDist=0;
for(i=0;i<8;i++) { nHammingDist+=Ham_count[uch[i]]; }

3)如果CPU支持sse4.2指令集的话,可以用sse扩展指令快速计算(intel core 2以上CPU/amd 推土机以上CPU)

#include //需要这个头文件(VS2008及以上的VS。gcc之类的不清楚)
int nHammingDist=_mm_popcnt_u64(a^b);

那么,上述三种快速算法的时间代价分别是多少呢?
测试方法:1,000个256bit数,每个在100,0000个256bit数中间找最近的那个数。计算总计花费的时间。(单核2.8GHz intel core i5 460m)
下面是实验结果:
方法1: 56s
方法2: 53s
方法3: 34s

由此可见,打表法比折半计算稍快(实际如果多线程同时处理的话,方法2会比方法1快10%以上,因为方法1需要ALU计算,而方法2基本不需要ALU)
方法3的利用sse4.2指令的方法是最快的,但需要CPU支持(不过按照电脑每5年左右会淘汰一次的角度来看,过几年就都支持了)

总结:算法再快,不如CPU硬件实现快……