LLVM小结
LLVM小结
如果说gcc是FSF的传奇,llvm就是Chris Lattner的小清新。当然啦,想具体看看这位四处游山玩水还GPA 4.0的大神和他的LLVM编译链还有他与苹果之间的故事的读者可以移步http://news.cnblogs.com/n/127343/。另外,据悉,FreeBSD自10.0开始将会完全采用llvm编译链编译,而之前的版本,与Linux一样,都是采用的gcc编译的。
以上,就算是“拉大旗扯虎皮”,既是给llvm做个简介,也是让大家知道本篇博文还是说的是比较“有用”的东西,而不是什么虚无飘渺的东西。
llvm在编译链中的环节其实是属于后端,前端可以采用gcc或者clang(从某些编译课程来看,用yacc和bison写的前端也行)。gcc想必大家都很熟悉,我也就不再赘述。clang则是专门为llvm定制的前端,据说当初开发它的一个很重要的因素就是gcc和IDE配合得不太好,而且gcc模块之间写得比较混杂,难以修改。作为前端,虽然我没有使用过配合clang的IDE(Apple developer能使用到的XCode算一个,不过我还没真正用过),但确实,在终端下调试的时候clang给出的输出比gcc的要好理解得多。不过clang是名副其实的CLang,只支持C/Obj-C/C++这三种语言;而gcc当然是无所不包无所不能的了。这里我上个C程序的例子吧(如果觉得不过瘾,你可以自行尝试C++,据说C++的类模板最能体现这两者的区别,也可以直接去http://blog.llvm.org/2010/04/amazing-feats-of-clang-error-recovery.html):

1 #include <stdio.h>
2
3 int main(){
4 return 1? 2 3
5 }

我们来看看clang和gcc给出的出错信息分别是什么(为了证实确实是这段程序,我先cat了它):

首先,其实gcc没有给全出错信息,如果你只照gcc的输出在第4行14列添加了冒号,那么你再次编译的时候它还会告诉你这一行的末尾缺分号;而clang不仅给全了错误而且每个错误都是出错信息一行,源代码一行,建议一行(note也是这样的),并且输出有色彩分别。笔者的gcc版本是4.7.3,clang版本是3.2-1,都是Ubuntu 13.04下最新的(顺带插一句:不知道为什么llvm 3.3已经发布很久了,Ubuntu还没有正式采用)。我觉得前端有一个很重要的功能就是报错,clang做得很好,至少这点比gcc做得好。苹果的产品在“看得见”的地方一向都做得很好,clang也是这样的。
编译器的前端,不仅要能生成AST,而且如果源代码有语法错误或者警告(虽然程序猿貌似都忽略警告,但实际上有的时候警告还是很有用的)要应当能给我们很好的指出,毕竟我们是人不是机器,要人性化一点;另外,后端又要能够在前端分析出的AST为程序做出极致的优化,当然,我不是说程序优化就靠编译器了,程序猿本身就应当编写出好的代码,但是编译器确实应当负责优化程序。llvm和gcc到底谁优化得更好,大家说法不一,给出的数据差距也很大,但是呢,不过呢,“LLVM has been awarded the 2012 ACM Software System Award!”,估计肯定是不会差的了。除了各种天花乱坠的数据外(如果非要看的话,我还是给个早年的数据吧:http://llvm.org/pubs/2007-07-25-LLVM-2.0-and-Beyond.pdf),毕竟程序最终是要给用户用的,毕竟用户体验才是最重要的,所以我们直接比较产品。举个栗子:LLVMpipe,这是一个类似于即时编译或者说在线编译的东西,它将OpenGL的代码(本来是抛给GPU的)编译为CPU可执行的代码并交由CPU执行。这个东西被很多支持老旧电脑的Linux发行版所采用,所以想来效率也不会太差。当然,效率高不高和运行快不快其实并不等价,因为运行快不快和具体的硬件环境还是有很大关系的。
说到编译优化,llvm似乎还有一个奇怪的优化方法:llvm(low level virtual machine)本身就是一种抽象的、虚拟的计算机架构,其特性介于RISC和CISC之间,llvm会先将代码编译为llvm架构的字节码(这里还是说说数据吧,从其官方数据来看,生成的字节码略多于x86的目标代码而少于SPARC的目标代码),然后可以对字节码进行JIT优化然后再翻译为目标架构的二进制代码。另外,llvm实际上采用的是一种全生命周期(lifelong)的优化策略(虽然还是很偏重静态优化),最直接的体现就是比起gcc能做到的 -O3,llvm可以做到 -O4,而且 -O4采用的是LLVMgold.so所提供的运行时库。llvm本身的设计思想就是希望做到编译时、链接时、运行时、空闲时的全方位优化。关于这些优化,在llvm官网可以找到,请移步http://llvm.org/pubs/2004-01-30-CGO-LLVM.html。
最后来说一下llvm和gcc的兼容性,我前面只是说了llvm的后端兼容gcc的前端生成的AST,其实llvm对gcc的兼容性是很高的,我现在系统的环境变量CC设置的就是clang,我编译了很多工程都不用改Makefile就可以成功编译,不过很多工程里只是采用的 -O2,让我略不爽,所以我就手动将之改为 -O4,当然也就需要修改一下CFLAGS和LDFLAGS,为之加上llvm-config的输出。llvm本身在脚本上就设计为和gcc的兼容,所以改换编译链十分容易。
开源库CImg 数据格式存储之二(RGB 顺序)
在上一篇博客中已经初步说明了GDI和CImg数据的存储格式感谢博友 Imageshop 评论说明
CImg的说明文档中已有详细说明(详见上篇博客说明)
CImg的数据格式确实是RRRGGGBBB顺序存储的已经毫无疑问,但是其参考手册中对其他GDI
的数据格式说明是略有瑕疵,参考手册说其他GDI的数据格式是RGBRGBRGB,其实则不是经过验证
bmp类型的数据格式应该是BGRBGRBGR 下面用code验证
说明:使用MFC 同时用CImage和CImg加载同一幅图片

void ImageIO::loadImage(const BiCImg & image, T*& pImagePlane,int& width,int& height,int& nchannels)
{
// get the image information width=image.width();
height=image.height();
nchannels=3;
int rgb_leng=width*height;
pImagePlane=new T[width*height*nchannels]; // check whether the type is float point
bool IsFloat=false;
if(typeid(T)==typeid(double) || typeid(T)==typeid(float) || typeid(T)==typeid(long double))
IsFloat=true; const unsigned char* plinebuffer;
plinebuffer=image.data(0,0);
for(int i=0;i<height;i++)
{
//plinebuffer=image.scanLine(i);
for(int j=0;j<width;j++)
{ pImagePlane[(i*width+j)*3]=plinebuffer[i*width+j+2*rgb_leng];//RGB b
pImagePlane[(i*width+j)*3+1]=plinebuffer[i*width+j+rgb_leng];//RGB g
pImagePlane[(i*width+j)*3+2]=plinebuffer[i*width+j];//RGB r }
}
}

上述为正确的顺序,若改为如下代码
pImagePlane[(i*width+j)*3]=plinebuffer[i*width+j];//RGB r
pImagePlane[(i*width+j)*3+1]=plinebuffer[i*width+j+rgb_leng];//RGB g
pImagePlane[(i*width+j)*3+2]=plinebuffer[i*width+j+2*rgb_leng];//RGB b
实验效果如下图

右图为原始图片,明显左图的蓝色部分取代了原始图片的红色应该是BGR缺写成了RGB
LLVM小结的更多相关文章
- Objective-C 里面的类对象复用小结
OC 提供了单继承 (Inheritance), Category, Extension, Protocol 这几种基本的类与对象层面的复用机制,作一小结. 在这几个机制中,继承提供了纵向的复用,可以 ...
- TVM量化小结手册
TVM量化小结手册 文章目录 Offical References TVM quantization roadmap INT8 quantization proposal Quantization S ...
- 从零开始编写自己的C#框架(26)——小结
一直想写个总结,不过实在太忙了,所以一直拖啊拖啊,拖到现在,不过也好,有了这段时间的沉淀,发现自己又有了小小的进步.哈哈...... 原想框架开发的相关开发步骤.文档.代码.功能.部署等都简单的讲过了 ...
- Python自然语言处理工具小结
Python自然语言处理工具小结 作者:白宁超 2016年11月21日21:45:26 目录 [Python NLP]干货!详述Python NLTK下如何使用stanford NLP工具包(1) [ ...
- java单向加密算法小结(2)--MD5哈希算法
上一篇文章整理了Base64算法的相关知识,严格来说,Base64只能算是一种编码方式而非加密算法,这一篇要说的MD5,其实也不算是加密算法,而是一种哈希算法,即将目标文本转化为固定长度,不可逆的字符 ...
- iOS--->微信支付小结
iOS--->微信支付小结 说起支付,除了支付宝支付之外,微信支付也是我们三方支付中最重要的方式之一,承接上面总结的支付宝,接下来把微信支付也总结了一下 ***那么首先还是由公司去创建并申请使用 ...
- iOS 之UITextFiled/UITextView小结
一:编辑被键盘遮挡的问题 参考自:http://blog.csdn.net/windkisshao/article/details/21398521 1.自定方法 ,用于移动视图 -(void)mov ...
- K近邻法(KNN)原理小结
K近邻法(k-nearst neighbors,KNN)是一种很基本的机器学习方法了,在我们平常的生活中也会不自主的应用.比如,我们判断一个人的人品,只需要观察他来往最密切的几个人的人品好坏就可以得出 ...
- scikit-learn随机森林调参小结
在Bagging与随机森林算法原理小结中,我们对随机森林(Random Forest, 以下简称RF)的原理做了总结.本文就从实践的角度对RF做一个总结.重点讲述scikit-learn中RF的调参注 ...
随机推荐
- 【高德地图API】从零开始学高德JS API(一)地图展现——仙剑地图,麻点图,街景,室内图
原文:[高德地图API]从零开始学高德JS API(一)地图展现——仙剑地图,麻点图,街景,室内图 摘要:关于地图的显示,我想大家最关心的就是麻点图,自定义底图的解决方案了吧.在过去,marker大于 ...
- Java初认识--函数和数组
一.函数 1.函数的定义 函数就是定义在类中的具有特定功能的一段独立小程序,函数也称为方法. java中最小的功能单元就是函数. 2.函数的格式 修饰符 返回值类型 函数名(参数类型 形式参数1,参数 ...
- mysql很全的和完整的总结
(1)数据类型 类型 备注 tinyint/smallint/mediumint/int/bigint 1B/2B/3B/4B/8B float/double 单精度/双精度浮点型 decimal 不 ...
- 原生js写的一个弧形菜单插件
弧形菜单是一种半弧式或者全弧形菜单,是一种不同于传统横向或者竖向菜单形式的菜单.最近在网上看到好多人写出了这种效果,于是也尝试自己写了一个. 实现方式:原生态js 主要结构: 1.参数合并 var d ...
- SQL Server 2012的附件失败,与硬链接的问题
1.我在系统上做了硬链接,也就是把C盘的某个目录,映射为D盘. 2.把数据库文件mdf和ldf放入D盘.结果,SQL Server的企业管理器,无法从D盘里加载mdf或ldf文件,并且在目录下无法显示 ...
- Spring之SpringMVC的Controller(源码)分析
说明: 例子就不举了,还是直接进入主题,本文主要是以SpringMVC的Controller接口为入点,来分析SpringMVC中C的具体实现和处理过程. 1.Controller接口 public ...
- css技巧--整理(1)
1.文字描边 -webkit-text-shadow:#be8ef8 2px 0 1px,#be8ef8 0 2px 1px,#be8ef8 -2px 0 1px,#be8ef8 0 -2px 1px ...
- Jumony快速抓取网页
Jumony快速抓取网页 --- Jumony使用笔记--icode 作者:郝喜路 个人主页:http://www.cnicode.com 博客地址:http://haoxilu.c ...
- valuechange(动态的监听input,textarea)
valuechange(动态的监听input,textarea)之前值,之后值的变化 jQuery封装自定义事件--valuechange(动态的监听input,textarea)之前值,之后值的变化 ...
- jQuery Tags Input 插件显示选择记录
利用jQuery Tags Input 插件显示选择记录 最近花了不少时间在重构和进一步提炼我的Web开发框架上,力求在用户体验和界面设计方面,和Winform开发框架保持一致,而在Web上,我主要采 ...