0%

Table of Content

  • Content
    {:toc}

Disable default driver

  1. modify /etc/modprobe.d/blacklist.conf by adding following commond at the end of the file:blacklist nouveau
  2. modify /etc/default/grub file by adding rdblacklist=nouveau nouveau.modeset=0

Install NVIDIA GPU Driver

  1. type ctrl+alt+F1 to tty and log in.
  2. shut down lightdm sudo service lightdm stop
  3. add source sudo add-apt-repository ppa:xorg-edgers/ppa,sudo apt-get update.
  4. install driver. Note that the version of the driver must be correspondent to the GPU card. One can find the correct version in NVIDIA official website. For example, my GPU is GTX970M, then I should use the following commend: sudo apt-get install nvidia-352 and sudo apt-get install nvidia-352-uvm
  5. reboot

Install CUDA Toolkit

  1. download CUDA 7.0 .run file from NVIDIA website. Note that the CUDA version should be correspendent to gcc version and driver version.
  2. change .run file mode by chmod +x *.run
  3. install CUDA by sudo ./*.run. Note to skip the installation of driver.
  4. add necessary environment path by PATH=/path/to/cuda/bin:$PATH and LD_LIBRARY_PATH=/path/to/cuda/lib64:$LD_IBRARY_PATH and export them. Alternatively, one can modify /etc/profile to set the environment paths. For example, add export PATH="/path/to/cuda/bin:$PATH" and in commond line type source /etc/profile
  5. verify the installation. Change directory to CUDA sample and make the samples. Run a sample sudo ./deviceQuery to verify the installation.

上篇博文里记述了我的一个梦,突然想到很久以前我也梦见过一个很离奇的梦,也是跟爱情相关。翻了自己在人人网上的日志终于找到了,是2007年12月的一个梦,刚刚上大学,真是年轻单纯啊,连梦的结尾都比最近的梦圆满。当时的梦境是:

某个年代(似乎是拿破仑时代,十九世纪二十年代左右),我在某个王国(欧洲风格),我有一个恋人,或者是认识了一个女孩(记不清了)。我不知道她的国籍,但我想和我一样,因为我们可以毫无障碍的交流。我看不清她的模样,在梦里她总是模糊的。我有个朋友是国王的近臣,他掌管军队的物资。

有一次,那个女孩要去一个城镇(忘了原因),女孩出发了,但我非常不安,便跟去了。有一天,在我们俩见面的时候,我看见她脚下的土地能够倒映她的身影,不是普通的阴影,而是像镜子一样的倒影,就好像水面一样,但倒影非常模糊。我又开始非常不安,就急切地劝她离开这个城镇。当我们刚刚骑马走出城,马就惊了,把我们两个人摔在了城外。这个时候突然地面开始抖动,发生了一场特别恐怖的地震。地震过后,我们俩回望那个城镇,它已经完全成为了废墟。我们都非常庆幸,但我并没有告诉她我都看到了什么。

平平安安地过了一段时间,国王派遣我去某个地方,那是个军队驻地。那个女孩在送我走的时候也看到我身下又很不清晰的倒影,并感到很焦虑。她就把这件事告诉了那个作大臣的朋友。当得知我去的那个地方的名字后,他十分吃惊。他说那个地方已经荒废了,那儿有个秘密建的非常大的火药库,但本来火药库不该建在那儿,所以马上就要被炸毁了。可能是有人想要害死我。就这样,那个朋友骑快马追上了我,秘密的告诉了我这些事。但我身边有个人总是在催促我赶快上路,说国王命令不能拖延。朋友无奈只得回去,那个女孩没办法,只好自己赶来了,不知道她怎么就让我在路上停留了一天(忘记原因了)。我们延迟了一天到达目的地,在转过一个小山包之前,我们听到了剧烈的爆炸声。转过山包,又是一片废墟。

最后,朋友为了我的安全,把我转移到了另一个国家,和我一起离开的还有那个女孩。朋友在送我走的时候说:真爱的人可以看清对方脚下的土地!

记得当时做这个梦醒来之后是一种精神饱满、神清气爽的感觉。最近的那个梦也是如此,但是结尾就显得比较隐晦,好像是绝望中隐含着希望,后来也没有再接着梦到这个故事了,姑且当做也有个圆满的结局吧。

昨天夜里做了个梦。

我叫刘亚楠,年龄应该是18-19岁左右。在A城某学校上学,这所学校绝不是现实中的大学,更像是培训中心,教会学生如何成为人类社会的一颗螺丝钉,如何为了人类的生存而服从管理。在这里,恋爱是被禁止的,因为一个人的未来已经被确定了,他或她以后有没有被计划结婚,繁衍几个后代都是确定的。但是,我和一个叫陈美玲的女孩恋爱了,虽然只能是地下恋情,我们依旧很开心。

终于有一天我们的事情暴露了,在傍晚天刚刚黑下来的时候,学校的负责人带着政府的人来抓我们。这一天天气阴沉,刚刚下过雨,道路湿滑,宿舍楼道里的黄色灯光十分昏暗,还在不停的抖动,时亮时暗。我的好朋友alice(一个有点男人婆的女生)跑来告诉我快逃,于是我拉着美玲逃出了学校。我清楚地记得当我们转过楼道尽头来到一侧的楼梯间时,来抓我们的人刚刚走出楼道另一侧的楼梯间,就这样他们错过了我们。

A城晚上是有宵禁的,无缘无故在外面瞎晃是会被抓起来的,于是我和美玲决定乘长途汽车先躲到临城,然后想办法逃到偏远地区生活。学校里,学校负责人发现我们不见了,要求学校里的所有老师和学生对学校和A城进行搜索。从A城出发的长途汽车站只有一个,位于一个叫“老城墙”的地方,而我们离这个地方很远,必须乘车才能到。为了不被学校的人抓到,我们必须去一个偏远的公交站坐车。在去公交站的路上,我们发现有学校的人,我们知道他们是来抓我们的,于是我们不得不去另一个更远的车站。在路上我们不停的跑,一是因为每天公交的班次是有限的,错过了就要几个小时以后才能有下一班,另一个原因就是我们害怕被抓到。

当我们跑到车站的时候,天已经完全黑了,街边立着不太亮的路灯,我们躲到车站旁边小巷的阴影里忐忑地等车,一边盼望着车快点来,一边紧张地关注着是不是有学校的人出现。当公交车缓缓的进站时,我们走出阴影,准备上车。这时,我突然发现有一群人向车站走来,他们是学校里的学生。这些人中有几个是和我熟识的朋友,其中一个是alice。还有一个小男孩,只有14-15岁,我们都管他叫“小孩”,因为他的年龄比我们都小,很可爱,而且善良单纯,别人说什么都信。我赶紧压低了美玲和我的帽檐,我只盼着他们不要在人群里把我们认出来,因为车已经停下来了,我们马上就可以上车了。这时来抓我们的人已经走到我们身边了,“小孩”就在我身边,我扭过脸怕被他发现,但是他还是发现了我,与我四目相对的一刻,我看到了他眼中的惊奇,或许他从来没有想到过真的可以找到我们,我冲他摇了摇头,希望他不用揭发我们。但是,在一丝犹豫之后,他还是向其他人大喊我在这里。这时车门开了,我一把把美玲推上车,而我被一只手抓住了,虽然我挣脱了那只手,但是我没能上车,我只能沿着路逃跑,我能看见美玲在车窗里流着泪向我比划着说到临城找她。

宵禁开始了,没有办法,我只能悄悄潜回了学校,躲进了存放打扫工具的房间,我锁上了门,但不敢打开房间里的灯,害怕被人发现。我躲进来不久,房门被钥匙打开了,我赶快躲到了一堆工具后面,但是进来的人没有开灯。我听见他们说话,是alice和“小孩”,alice指责“小孩”为什么要揭发我,“小孩”说是因为老师要求的,alice很无奈,只好让“小孩”先回去了。过了一会儿,alice也出去了,从外面锁了门。等了一会儿,我刚刚感觉到放松,想从工具后面出来,找个舒服一点的地方打个盹,这时门锁又被转动了,进来一个膀大腰圆的男人,他打开灯,一个箭步就把我从工具后面抓了出来…

醒了。

最近听电子书,搞了一本英音原本的《哈利波特》,不禁想起“年轻”时写的一篇博文,粘来应应景。

那时刚刚在影院看了《哈利波特与混血王子》,感觉这是除了第一部和第二部之外拍的最好的一部,不过依旧是观前期待很大,观后略微失望的感觉。这一部仍然延续了前几部灰暗阴冷的风格,即使在比较热情的魁地奇赛场上也没有太多的暖色调,朦胧的爱情也没有沉浸在玫瑰的红艳之中。虽然这一部本来就很阴郁,但缺少暖色总是让电影给人一种沉闷的感觉,紧张的情绪也总得不到调节,对于一部将近三个小时的电影来说难免令人感到精神疲劳。

最初接触哈利系列是在电影院,应该是初中的时候,那个时候对哈利系列完全是一种不屑的心态,因为不管是《魔法石》还是《密室》都是纯纯粹粹就是儿童影片,没有什么新意,而且剧情雷同。和其他人不同,我连一本哈利系列的小说都没有买,也没用兴趣去读这样一部儿童读物,即使有同学跟我争论说这是一部老少皆宜的作品,我也不以为然。相反,我对另一部英国魔幻作品《指环王》却是出奇的着迷,或许是其磅礴的诗史气魄格外吸引人,所以我也读了《指环王》原著的三部曲及其前传,而对哈利系列始终没有兴趣。

在大二上学期,花了两个月读完哈利系列,对这部作品有了一些新的看法。这部作品给我最大的印象就是它是一个关于成长的故事,它的出版速度十分符合我们这一代人成长的时间进程,1997年第一部出版到2007年最后一部完结,从十来岁的少年到十八九的青年正好被七部小说的出版所覆盖,小说的内容也逐渐成人化。从小孩子对魔法的好奇与向往开始,第一二部里神奇的魔法世界,诡异的车站,骑着扫把飞翔的魔法师,独特的魁地奇……等等一些新奇的玩意儿给小孩子们很多充满想象力的冲击,这时的电影风格也是暖色调居多,尤其第一二部完全可以当做独立电影来看待,完整的故事情节,绚丽的电脑特技和圆满的结尾都让它成为不错的儿童电影;后来便开始了成长的烦恼,从第三部起,一直到第五部,我认为小说都是在重复第一二部的故事结构,没有什么创新,而且故事之间的连续性很差,估计唯一的联系就是伏地魔逐渐强大起来,给最后两部做个蹩脚的铺垫,在读小说的过程中,读第一二部还觉得不错,但是第三部开始便开始感觉到有一些厌烦。电影也是如此,类似的故事结构,没有什么新意的特效,四平八稳的指导,都没让这三部电影给人留下深刻的印象。到了第六部和第七部,故事才有所转折,而且这里主人公也已经开始体验亲情,友情,爱情,背叛,忠诚,正义,邪恶……小说的高潮也从此开始。但是电影依旧没有什么太大的起色,对原著的改编也并不成功,而且越到最后对于那些没有看过原著的观众来说,电影越来越难以理解。

对于哈利系列,原著比电影应该更吸引人,而且阅读给人留下的想象空间更广大,也正是因此对于忧郁的中间几部而言,总会有一些令人放松精神的篇章,在这些地方读者不会受困于电影画面的禁锢而不得不继续忧郁着。

My name is Li Zhixuan, currently a computer vision engineer in Beijing, China. If you like, you can call me Joshua, which sounds more or less like my Chinese given name.

I did not notice that I am already a writer until I drew the time line of my humble writing career. The first memories of my starting writing are those diaries that I kept in summer holidays according to my Chinese teacher’s request when I was in grade six to eight. At that time, I just hated writing because I did not know what to write about due to not many meaningful things happened in holidays. Besides, being unable to tell a story lively made me feel pathetic and inferior. However, sometimes I did feel happy about my writings. I remembered that I wrote a short story about how I was annoyed by mosquitoes and got up killing them in a summer night. The story was written in ancient Chinese style imitating a text from my Chinese textbook. I got a Bravo from my Chinese teacher and she said it was really funny to read. Though I still suffered from lack of words and telling stories like presenting facts, I began to feel free to write and cultivated a habit of keeping diaries from then on. Thanks to that, I got three huge notebooks full of growing pains in my “secret chamber”.

I began to know academic writing when I was in university. There were many courses that required an essay for evaluation. From the reference papers, I learnt to propose problems, explain solutions and presenting evidence of effectiveness and feasibility. Unlike most of my peers feeling awful about writing their Master degree dissertations, I felt quite comfortable with it mainly because I had much to share with others. My dissertation was about detecting certain events in surveillance videos. I was so eager to share with others about how meaningful the task was, what flaws current algorithms had and how I improved them that it was as if everything was just bursting out of my mind. Although I write much in Chinese, I have little experience of writing academic papers in English. The only experience is a paper I wrote about detecting pedestrians in images, which was a part of work from my Master dissertation and the paper was published in an international conference. It was because of the conference that I got a chance to visit Krakow, a beautiful historical city in Poland. I felt really proud of myself presenting my work in the conference and it was really a pleasant trip to Krakow, appreciating its marvelous beauty and culture.

Currently, I am working in an IT company and writing patents, project documentation and slides is also my responsibility. In addition, I am writing this blog. Those are some of the reasons I am taking this course. I wish I could really improve myself and have fun with writing!

最近在看一个特别古老的美剧《X档案》,特别小的时候断断续续看过一些,记得好像是在中央八电视剧频道演过。在Wiki上这个剧被定义为science fiction horror drama television series,听起来好像挺奇怪的,科幻恐怖剧。看了看还真是挺恐怖的,不知道小时候看这个是不是被吓得够呛。虽然这个剧有点年头了,1993-2002年在FOX电视台播出,但是现在再看剧情和拍摄手法依旧很吸引人,而且正是由于拍摄久远,导致画面很模糊,给这部电视剧添加了一种莫名的神秘感,模模糊糊的画面好像有意遮挡了一些真相,更符合这部剧的风格。

这部剧涵盖了外星人、超自然现象、政府骗局和阴谋论等等所有相关主题。其中印象最深刻的是第一季第10集还是第11集中的一小段片段,估计对我当时还幼小的心灵造成过心理阴影。这还得从小时候读到的一些东西说起,那时候经常读一些科幻或者科普的书或杂志,里面记录了很多科学之谜和UFO目击者的谈话记录,比如麦田怪圈和被外星人绑架什么的。有一段是讲一个农场里的牛一夜之间都死掉了,而且全都被割去了一只耳朵和一片嘴唇,但是农场主却没有察觉到任何异常,于是就有人解释说是外星人干的。看过这个故事之后,特别害怕自己那一天也会被外星人绑架,然后被割掉耳朵和嘴唇。后来在电视剧里有类似的剧情出现,女主问男主这样做的意义在于什么,男主回答说就好像我们解刨鱼和青蛙一样,这话真是说得令人毛骨悚然啊。也真是佩服自己小时候竟然受到过这么大的刺激,不知道这部电视剧在美国是不是儿童限制级。现在网络这么发达,估计现在的小孩可以接触到更恐怖的信息,不知道对他们来说是不是也埋藏了各种心理阴影。

最近出游比较多,五一假期之前的周末随公司去云蒙山爬山,假期去了无锡和苏州,张大夫在南京研究各种花花草草,让人不得不好好热爱了一把生活。其实说起出游,真正让我开始感觉到应该多去走走、体验不一样的生活,是去波兰的克拉科夫Krakow参加2013年的International Conference on Advanced Video and Signal based Surveillance,也是从那个时候开始让我觉得一个人出游的乐趣。在克拉科夫逛了很多地方,感受了当地丰富多彩的文化。因为是自己一个人,所以逛的很惬意,全程都是徒步,累了就在街边的露天餐馆歇一歇,其实就好像咱们国内的大排档,只不过对咱们来说少了烧烤的油烟,多了点小资的味道,喝点汤吃点面包,恢复恢复体力。本想回来好好记录一下这三天在克拉科夫的见闻,一犯懒一晃一年半过去了,记忆也都模糊了,不过能想起来的肯定都是精髓了。

8月26日俄航凌晨的飞机飞往莫斯科,由莫斯科转机到克拉科夫,网上说俄航的服务态度很差、经常丢行李,在莫斯科转机安检也很麻烦,不过我个人感觉还好,没有遇到什么太大的麻烦,但是由于航班的缘故,在莫斯科机场呆了四五个小时,没有当地签证,就只能干坐着,蹭着机场里龟速的WIFI发了两篇微博。飞机上最激动人心的就是看日出了,还没见过黄山的云海日出,先拿飞机上的充数吧。亲近亲近大自然,感受伟大的造物主,瞬间就会让生活中的磕绊困难显得渺小,充满了信心去生活,所以总有人说“去散散心吧”,大概就是因为如此吧!

从莫斯科往克拉科夫是只坐大约100人的小飞机,还是第一次坐这么小的飞机,起飞降落的时候还挺刺激的,遇到气流颠簸的更厉害点,水平震荡的幅度也大,感觉这才叫飞行,以前的飞行家还真是得有点冒险精神才行。

在克拉科夫的住处是一个离中心市集广场只有50米的小旅馆,旅馆在一个窄窄的幽静的小巷子里,住宿条件很一般,不过是那种特别典型的欧洲老房子,石头砌的墙壁,大大的木门、陡峭的木楼梯、吱吱作响的楼板。沿着小巷到中央市集广场就变得热闹多了,广场中心是一个大市场,算是市民生活的中心了。对于这个广场,我记忆最深刻不是市场本身,而是坐落在广场南侧的圣玛丽教堂,这个教堂有两座钟楼,较高的一栋是尖顶,另一栋是穹顶,大概是因为教堂修建历时太久,流行的风格已经变了。每隔一个小时,从钟楼顶部都会响起号角声,戛然而止的号角声让人感觉曲子是突然中断的,这是为了纪念13世纪的一名号手,他在蒙古人袭击城市时发出警报而被弓箭射中喉咙,正午的号角声由波兰国家电台向波兰国内外播放。这个故事给我留下了特别深刻的印象,以至于在我准备雅思口语时,把在这里的见闻作为回答有关建筑、旅行主题的素材。

克拉科夫是一座古老的城市,在公元700年前后建成,所以城中的建筑风格多种多样,有很多有趣的现象。例如刚刚说到的不对称的圣玛丽教堂,更有趣的是广场西南角的圣亚德伯堂,这座教堂有上下两层,下层是一个半地下室。实际上,这是两座教堂,半地下室是一座更为古老的教堂,在这座老教堂的正上方又重修了一座新教堂。一个有趣的说法是在古时候,人们不注意卫生,垃圾满街乱堆乱扔,久而久之真个城市的地面就被垫高了,最后不得不重修建了一座教堂。不知道这个说法的真实性怎么样,不过在克拉科夫确实有很多半地下室。

另一个不得不提的是坐落在城外瓦维尔山上的一座城堡——瓦维尔城堡,城堡背后是维斯瓦河,算是一个易守难攻的地方。在这里有着最古老的骑士屠龙的传说。很久很久以前,在瓦维尔山下维斯瓦河边的洞穴里住着一头恶龙,它要求人们每个月进贡一名美貌的少女让它吃掉。国王为了拯救全城的百姓许诺谁杀了这头邪恶的龙,他就把自己的女儿嫁给这位英雄。不过屠龙的并不是骑士,而是一名鞋匠铺的小学徒。他引诱龙吃下了塞满硫磺的羊,被烧的难受的龙拼命地喝维斯瓦河里的水,最后撑破了胃死去。后来国王就在这个地方建立了克拉科夫城,在瓦维尔山上建起了瓦维尔城堡。从此,小学徒和公主幸福地生活在城堡里。

城堡的正中央有一组废墟,那是最初城堡的所在地,很小,随着时间的推移,城堡不断扩建,变成了现在的模样。其中的瓦维尔主教座堂据说包含了欧洲几乎所有的建筑风格,研究欧洲建筑如果没有来考察过瓦维尔主教座堂可算是不称职的。城堡里有博物馆,藏有达芬奇的名画《抱银鼠的女子》。另一个让我惊喜的是见到了波兰翼骑兵的盔甲,记得小时候玩《帝国时代II》,其中的斥候骑兵就是背后插翅膀的,当时还觉得居然有这么奇怪的骑兵,这次算是见到真品了。抄一段百度百科上的话

13世纪,波兰人面对的主要敌人有两个:西北面的条顿骑士和东面的蒙古人。面对东线开阔的地形和机动的蒙古骑兵,波兰军不堪一击,1241年连当时的首都克拉科夫都让蒙古人给洗劫了一道。从14世纪起波兰的主要敌人是西边的条顿骑士,15世纪的13年战争是波兰崛起的开始。通过这场战争,波兰不仅驱逐了条顿势力,同时也锻炼了一支军队,其中以翼骑兵最为著名。

克拉科夫还是一座宗教城市,诞生了第一位波兰籍的教皇——约翰·保罗二世。约翰·保罗二世曾经发表过一些有关教会与犹太人关系的演讲,并经常对在犹太人大屠杀牺牲的犹太人表示敬意。1979年,他成为了第一个访问波兰奥斯威辛集中营的教皇。他是少数在犹太文化下长大的教皇。2000年3月,他访问耶路撒冷,他说:“犹太人是我们的兄长。”一些人认为这是承认天主教由犹太教所分出来,而耶稣最早的跟随者是犹太人。在城内一个神学院的窗口上有一幅他的画像,据说在成为教皇以前,作为克拉科夫的总主教,他经常坐在这个阳台上,与窗口外的神学院的学生和克拉科夫的市民交谈。在克拉科夫可能有上百座大大小小的教堂,包括一些已经成为废墟的教堂都被保留了下来。

还有一个大家熟知的故事也发生在这里,这就是《辛德勒的名单》。克拉科夫的卡齐米日地区,就是这部电影的舞台原型。很多年前看这部电影的时候,我从未想过自己可以走进电影中的场景。电影中很多实景在此拍摄,至今还可以找到。在这个工厂附近有很多犹太人的墓地,很多墓主人都是纳粹时期罹难的。英雄广场上有68张铜椅子组成的雕塑群,代表着曾在这里生活过的6.8万犹太人。空旷的广场,空荡荡的椅子,一派肃杀。身处其中不禁叹气,心中荡起无限悲凉。

最后说说维耶利奇卡的盐矿,公元八世纪的时候,这里发现了岩盐矿,十一世纪时开始大规模开采,十三世纪以后成为重要的岩盐来源,也成为波兰的重要财政来源。地下盐矿共九层,第一层距地面65米,第九层深达327米。坑道总长达到300公里,向游客开放大约10公里。这里的矿工不是奴隶或者赤贫者,他们有着很高的社会地位,收入丰厚并且受人尊敬。在漫长的岁月中,矿工们形成了把岩盐原料雕刻成各种物品的传统,地下教堂、圣坛、浮雕以及数以百计的真人大小的雕像都是他们的杰作。维耶利奇卡盐矿最大的礼拜堂位于地下101米处,长50多米,宽15米,高12米。其中有一幅盐雕的最后的晚餐,浮雕深度只有几厘米,但是从特定角度观察却立体感十足,令人称奇。每位游客还可以领取一袋这里出产的原盐,自己尝了尝,还是很咸的。

克拉科夫相对那些更为热门的欧洲旅游城市更为恬静舒适,而且处处都是景点,走几步就可以停下来细细的品味,特别适合溜溜达达的闲逛,让人自然而然地放松。

2014年4月的时候自己在公司就将Caffe移植到Windows系统了,今年自己换了台电脑,想在家里也随便跑跑,本来也装了Ubuntu可以很方便的配置好,无奈在家的风格是“娱乐的时候抽空学习”,所以移植到Windows还是很有必要的。但是,公司禁止将公司内部资料带出,很多地方又都忘记了,周末磨了一天终于移植完,本篇为记录将Caffe移植至Windows7 x64系统下的一些关键步骤。下面介绍如何从源码建立VS2013工程。

Table of Content

  • Content
    {:toc}

1. 下载源码

https://github.com/BVLC/caffe下载caffe源码,master或者dev版本都可以,本文中以dev为例

2. 建立工程

新建一个空的控制台VS2013工程,起名为caffe-dev。

File —> New —> Project

选择Win32 Console Application

选择工程路径,比如D:\CODE\CXX

给项目命名caffe-dev

单击OK后选择Empty project

3. 将工程的Solution Platform改为x64

Build —> Configuration Manager —> Active solution platform —> new —> x64 —> OK

4. 设置CUDA编译

Project —> Build Customizations… —> CUDA 7.0 —> OK

5. 设置一些工程下的路径

注意Debug和Release下都要设置

在Project —> Properties —> Configuration Properties —> VC++ Directories —> Include Directories中添加openblas、opencv、boost和cuda,例如

1
2
3
4
5
D:\LIBS\boost_1_57_0;D:\LIBS\OpenBLAS\include
D:\LIBS\opencv\build\include
D:\LIBS\opencv\build\include\opencv
D:\LIBS\opencv\build\include\opencv2
C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v7.0\include

在Project —> Properties —> Configuration Properties —> VC++ Directories —> Library Directories中添加openblas、opencv、boost和cuda,例如

1
2
3
4
D:\LIBS\OpenBLAS\lib
D:\LIBS\opencv\build\x64\vc12\lib
D:\LIBS\boost_1_57_0\lib
C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v7.0\lib\x64

6. 拷贝源码

将压缩包内的include、src和tools文件夹拷贝到工程根目录下,同时把整理好的3rdparty文件夹也拷贝到工程目录下

7. 添加第三方依赖库路径

添加caffe的路径和3rdparty中第三方依赖库的路径,同样Debug和Release都要设置

在Project —> Properties —> Configuration Properties —> C/C++ —> General —> Additional Include Directories中添加

1
2
3
4
../include;../src
../3rdparty/include
../3rdparty/include/hdf5
../3rdparty/include/lmdb

在Project —> Properties —> Configuration Properties —> Linker —> General —> Additional Library Directories中添加

1
../3rdparty/lib

在Project —> Properties —> Configuration Properties —> Linker —> Input —> Additional Dependencies中添加

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
opencv_core2410.lib
opencv_highgui2410.lib
opencv_imgproc2410.lib
cudart.lib
cublas.lib
curand.lib
gflags.lib
libglog.lib
libopenblas.dll.a
libprotobuf.lib
libprotoc.lib
leveldb.lib
lmdb.lib
libhdf5.lib
libhdf5_hl.lib
Shlwapi.lib

注意在Debug下应添加xxxd.lib形式的静态库

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
opencv_core2410d.lib
opencv_highgui2410d.lib
opencv_imgproc2410d.lib
cudart.lib
cublas.lib
curand.lib
gflagsd.lib
libglogd.lib
libopenblas.dll.a
libprotobufd.lib
libprotoc.lib
leveldbd.lib
lmdbd.lib
libhdf5.lib
libhdf5_hl.lib
Shlwapi.lib

8. 生成pb文件

利用protoc.exe和caffe.proto生成caffe.pb.h和caffe.pb.cc文件

在编译protobuf的时候会生成一个可执行文件protoc.exe,在工程的D:\CODE\CXX\caffe-dev\src\caffe\proto路径下有一个文件叫caffe.proto,可以将protoc.exe拷贝到该路径下,在命令行中进入D:\CODE\CXX\caffe-dev\src\caffe\proto路径,输入命令

1
protoc.exe caffe.proto --cpp_output=./

可以看到在该路径下会生成caffe.pb.h和caffe.pb.cc,在D:\CODE\CXX\caffe\include\caffe中新建一个文件夹proto,将生成的两个文件移动到D:\CODE\CXX\caffe\include\caffe\proto中

9. 准备mkstemp.h和mkstemp.cpp文件。

将mkstemp.h放在include/caffe/util/路径下,mkstemp.h中的内容为

1
2
3
#include <windows.h>
#include <io.h>
int mkstemp(char *templates);

将mkstemp.cpp放在src/caffe/util/路径下,mkstemp.cpp中的内容为

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
/* mkstemp extracted from libc/sysdeps/posix/tempname.c.  Copyright
(C) 1991-1999, 2000, 2001, 2006 Free Software Foundation, Inc.

The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version. */

#include "caffe/util/mkstemp.hpp"
#include <errno.h>
#include <fcntl.h>
#include <sys/stat.h>

static const char letters[] =
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";

/* Generate a temporary file name based on TMPL. TMPL must match the
rules for mk[s]temp (i.e. end in "XXXXXX"). The name constructed
does not exist at the time of the call to mkstemp. TMPL is
overwritten with the result. */
int mkstemp (char *tmpl)
{
int len;
char *XXXXXX;
static unsigned long long value;
unsigned long long random_time_bits;
unsigned int count;
int fd = -1;
int save_errno = errno;

/* A lower bound on the number of temporary files to attempt to
generate. The maximum total number of temporary file names that
can exist for a given template is 62**6. It should never be
necessary to try all these combinations. Instead if a reasonable
number of names is tried (we define reasonable as 62**3) fail to
give the system administrator the chance to remove the problems. */
#define ATTEMPTS_MIN (62 * 62 * 62)

/* The number of times to attempt to generate a temporary file. To
conform to POSIX, this must be no smaller than TMP_MAX. */
#if ATTEMPTS_MIN < TMP_MAX
unsigned int attempts = TMP_MAX;
#else
unsigned int attempts = ATTEMPTS_MIN;
#endif

len = strlen (tmpl);
if (len < 6 || strcmp (&tmpl[len - 6], "XXXXXX"))
{
errno = EINVAL;
return -1;
}

/* This is where the Xs start. */
XXXXXX = &tmpl[len - 6];

/* Get some more or less random data. */
{
SYSTEMTIME stNow;
FILETIME ftNow;

// get system time
GetSystemTime(&stNow);
stNow.wMilliseconds = 500;
if (!SystemTimeToFileTime(&stNow, &ftNow))
{
errno = -1;
return -1;
}

random_time_bits = (((unsigned long long)ftNow.dwHighDateTime << 32)
| (unsigned long long)ftNow.dwLowDateTime);
}
value += random_time_bits ^ (unsigned long long)GetCurrentThreadId ();

for (count = 0; count < attempts; value += 7777, ++count)
{
unsigned long long v = value;

/* Fill in the random bits. */
XXXXXX[0] = letters[v % 62];
v /= 62;
XXXXXX[1] = letters[v % 62];
v /= 62;
XXXXXX[2] = letters[v % 62];
v /= 62;
XXXXXX[3] = letters[v % 62];
v /= 62;
XXXXXX[4] = letters[v % 62];
v /= 62;
XXXXXX[5] = letters[v % 62];

fd = open (tmpl, O_RDWR | O_CREAT | O_EXCL, _S_IREAD | _S_IWRITE);
if (fd >= 0)
{
errno = save_errno;
return fd;
}
else if (errno != EEXIST)
return -1;
}

/* We got out of the loop because we ran out of combinations to try. */
errno = EEXIST;
return -1;
}

10. 将caffe的源文件添加到工程中

将D:\CODE\CXX\caffe-dev\src\caffe路径下除了test文件中的所有源文件添加到工程中,如果想要跑一些测试代码,也可以把test中的源文件加进去

将D:\CODE\CXX\caffe-dev\include\caffe\proto下的caffe.pb.cc添加到工程中

将D:\CODE\CXX\caffe-dev\tools下的caffe.cpp添加到工程中

11. 修改一些代码

在include/caffe/common.hpp中添加#include <direct.h>

在include/caffe/util/io.hpp中添加#include "mkstemp.hpp",并将close函数替换为_close,将char* mkdtemp_result = mkdtemp(temp_dirname_cstr);替换为errno_t mkdtemp_result = _mktemp_s(temp_dirname_cstr, sizeof(temp_dirname_cstr));

将bnll_layer.cu中的const float kBNLL_THRESHOLD = 50.;修改为#define kBNLL_THRESHOLD 50.

将util/db.cpp中的mkdir(source.c_str(), 0744)修改为_mkdir(source.c_str())

将util/io.cpp中的open函数替换为_openclose函数替换为_close

将util/io.cpp中ReadProtoFromBinaryFile函数中的int fd = open(filename, O_RDONLY);替换为int fd = open(filename, O_RDONLY | O_BINARY);

在util/math_functions.cpp中添加

1
2
#define __builtin_popcount __popcnt 
#define __builtin_popcountl __popcnt

在common.cpp中添加#include <process.h>

pid = getpid();替换为pid = _getpid();

注释掉::google::InstallFailureSignalHandler();

将solver.cpp中的snprintf函数替换为sprintf_s

编译吧!!!!

2014年4月的时候自己在公司就将Caffe移植到Windows系统了,今年自己换了台电脑,想在家里也随便跑跑,本来也装了Ubuntu可以很方便的配置好,无奈在家的风格是“娱乐的时候抽空学习”,所以移植到Windows还是很有必要的。但是,公司禁止将公司内部资料带出,很多地方又都忘记了,周末磨了一天终于移植完,本篇为记录将Caffe移植至Windows7 x64系统下的一些关键步骤。第一步先看看这老些依赖库怎么搞。

在真正开始编译各依赖库之前,需要准备一些必备工具:

首先当然是VS2013,下载地址:https://www.visualstudio.com/

其次是CMake工具,下载地址:http://www.cmake.org/download/

Table of Content

  • Content
    {:toc}

1. Boost

下载地址:http://www.boost.org/

编译方法:

  1. 运行Visual Studio Tools中的VS2013 x64 Cross Tools Command Prompt终端工具
  2. 从终端进入boost库所在目录,如D:\LIBS\boost_1_57_0
  3. 运行bootstrap.bat生产64位的bjam.exe
  4. 输入命令进行编译,更正一下,msvc-12.0才是vs2013哈

静态库:bjam —build-type=complete toolset=msvc-9.0 toolset=msvc-12.0 threading=multi link=static address-model=64

共享库:bjam —build-type=complete toolset=msvc-9.0 toolset=msvc-12.0 threading=multi link=shared address-model=64

2. OpenCV

下载地址:http://opencv.org/downloads.html 本文中使用的是2.4.10版本

编译方法:

下载后的安装包中有已编译好的库,可直接引用,如D:\LIBS\opencv\build\x64\vc12

3. OpenBlas

下载地址:http://sourceforge.net/projects/openblas/files/

编译方法:

OpenBlas库在windows上编译起来比较复杂,这里给出的下载地址是一个已编译好的压缩包OpenBLAS-v0.2.14-Win32.zip (12.1 MB),直接提供了./bin ./include ./lib路径

4. CUDA

下载地址:https://developer.nvidia.com/cuda-downloads

编译方法:

与OpenCV类似,安装好后直接有已编译好的库。如C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v7.0\include和C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v7.0\lib\x64

以上是依赖库比较常用,最好将该它们的include和lib加入到Windows的环境变量中,方便后续的库的编译

5. GFlags

下载地址:https://github.com/gflags/gflags

编译方法:

  1. 启动CMake(cmake-gui)工具
  2. 设置source code路径和build路径
  3. 单击Configure按钮,并选择并选择Visual Studio 12 2013 Win64编译器编译器
  4. 更新完成后,勾选中BUILD_SHARED_LIBS和BUILD_STATIC_LIBS
  5. 单击Generate按钮,生成VS工程
  6. 打开刚刚生成的VS工程,build其中的ALL_BUILD工程,注意选择x64模式,并分别生成Debug和Release下的库
  7. 编译成功后,在工程路径下会生成bin、include、lib三个文件夹

6. GLog

下载地址:https://github.com/google/glog

编译方法:

该工程中包含VS工程google-glog.sln,打开直接编译即可,同样注意Solution Platform选择x64模式,并分别生成Debug和Release下的库

7. LevelDB

下载地址:https://github.com/bureau14/leveldb

这里没有选择官方的https://github.com/google/leveldb是由于官方版本移除了CMake的依赖项,自己写起来比较复杂

编译方法:

与编译GFlags方法类似,唯一需要注意的地方是将CMakeLists.txt中第82行的-DSNAPPY注释掉,否则需要依赖Snappy库,其实并不绝对需要,为了简单起见将此库去掉。另外Leveldb依赖于boost库,如果没有将boost库添加至环境变量,可能需要手动进行设置。

8. LMDB

下载地址:https://gitorious.org/mdb/mdb/archive/462dc097451834477b597447af69c5acc93182b7.tar.gz

编译方法:

  1. 解压压缩包到某路径,例如D:\CODE\CXX\mdb-mdb
  2. 在VS2013中新建工程,FILE —> New —> Project From Existing Code..
  3. 选取源码所在路径,并给工程起名
  4. 单击next按钮后选择Project type为Console application project
  5. 将Solution Platform修改为x64模式
  6. 注意将工程的输出改为静态库,右键单击工程 —> property —> Configuration Properties —> General —> Project Default —> Configureation Type —> Static library (.lib)
  7. 其中一个.c文件中包含了unistd.h,为了解决这个问题需要准备三个文件 unistd.h、getopt.h、getopt.c。unistd.h可以考http://stackoverflow.com/questions/341817/is-there-a-replacement-for-unistd-h-for-windows-visual-c解决。另外两个可以从http://ieng6.ucsd.edu/~cs12x/vc08install/getopt9.zip下载
  8. 最后编译即可

9. ProtoBuf

下载地址:https://github.com/google/protobuf

编译方法:

压缩包里有一个叫vsprojects的文件夹,其中有现成的VS工程,可以用来直接编译,也需要注意将Solution Platform修改为x64模式

10. HDF5

下载地址:http://www.hdfgroup.org/ftp/HDF5/current/src/CMake/hdf518-CMakeWindows.zip

编译方法:

解压后,在VS2013 x64 Cross Tools Command Prompt终端工具中运行build-VS2013-64.bat即可。

整理头文件和库文件

将5-10的头文件和编译后的库统一整理到一个3rdparty文件夹下,其中包含两个文件夹include和lib

include文件夹下包含gflags、glog、google、hdf5、leveldb、lmdb六个文件。gflags的头文件来自于生成的VS工程目录中的include文件夹;glog的头文件来自于VS工程目录中的src\windows文件夹;google中是protobuf的头文件,来自于压缩包中的src\google文件夹;hdf5来自于压缩包中的CMake\hdf5-1.8.14\src文件夹,保留.h文件即可;leveldb的头文件来自于压缩包的include文件夹;lmdb的头文件来自于压缩包中的libraries\liblmdb文件夹,保留.h文件即可

lib文件夹中的.lib文件直接从编译好的工程目录下拷贝即可,注意debug模式下的.lib文件的文件名修改为xxxd.lib形式

至此,caffe需要的各项依赖库已经准备完毕,后续会上一些图,看起来直观一些。