当前位置:  编程技术>c/c++/嵌入式
本页文章导读:
    ▪How to build C++/CLI target to .net 2.0 without vs2008      摘要 本文介绍如何在没有vs2008的情况下,将C++/CLI程序编译成.net 2.0版本 本文首发与我的个人博客:How to build C++/CLI target to .net 2.0 without vs2008自从vs2010开始,vs调整了对C++编译的策略,使用MSBui.........
    ▪遇见C++ AMP:GPU的线程模型和内存模型      遇见C++ AMP:GPU的线程模型和内存模型  Written by Allen Lee  I don't care where the enemies are / Can't be stopped / All I know / Go hard– Linkin Park, Lost In The Echo C++ AMP、CUDA和OpenCL,选择哪个?  &n.........
    ▪统计元素个数-list妙用      在python俱乐部里,看到的一个用法,觉得不错,收下了。#encoding:utf8mylist = [2,2,2,22,2,2,3,3,3]myset = set(mylist)for item in myset:    print mylist.count(item),"of",ite.........

[1]How to build C++/CLI target to .net 2.0 without vs2008
    来源:    发布时间: 2013-10-14

摘要

本文介绍如何在没有vs2008的情况下,将C++/CLI程序编译成.net 2.0版本

本文首发与我的个人博客:How to build C++/CLI target to .net 2.0 without vs2008

自从vs2010开始,vs调整了对C++编译的策略,使用MSBuild模式,该模式对于将早期的vs2008开发的项目迁移至vs2010是有利的,但是如果用户没有vs2008,但有vs2010,却不能将C++/CLI项目编译成.net 2.0,只能是4.0。查遍网上的解决方案,几乎一致的方案是安装vs2008(3G+)。本文针对这个问题,给出一个不安装vs2008的绿色环保方案(大约200多M)。拯救我们的硬盘空间吧!

 

缘起

项目基于C++/CLI封装了BMC Remedy C API,最初我的开发环境是VS2010和VS2012(自从用了VS2012后,我发现其对C++的支持可谓空前的优秀),编译的托管dll是基于.net 4.0的,本来以为只要不用2.0以上的特性,可以轻松的将目标平台降到2.0,但是当我将Project文件中的targetframework设置为2.0后,本以为“巧妙的”解决了问题了。但是当编译基于2.0的C#项目时(该项目引用了这个C++/CLI项目),报错为“2.0项目不能引用高版本的4.0”。不是明明设置成2.0了吗?后来用ILSpy查看,的确编译出来的C++/CLI的dll是基于4.0的。怎么回事呢?经过反复的查询,必须安装vs2008才能编译出.net 2.0的C++/CLI程序集。我的天哪,要知道我已经安装有vs2010和vs2012了,硬盘实在不能承受啊,无奈之下只能先在其他机器上安装vs2008了。当然问题最后的确是解决了,但是作为一个正儿八经的项目不能这么就结束了,于是便有了本文的探讨。

 

各取所需

对于仅仅需要编译C++而安装vs2008实在是不划算。仔细想来,vs2008是个集成开发环境,编译普通的C++程序大约只需要C++编译和链接器、动态和静态链接库、导入库即可,而对于MFC、ATL等也只是在这个基础上增加了更多的库而已。对于C++/CLI程序的编译大约增加了.net framework。还记得每个版本的visual studio都提供一个命令行工具吗?该工具会帮我们设置各种环境变量,在这个命令行中可以手动执行各种编译动作。想到这里,是否能够将vs2008中的C++编译所需要的工具和库文件从vs2008中提取出来,再加上一个命令行工具,就可以在没有vs2008的情况下编译我们的dll了,这样一个绿色的编译环境会完成了啊~相信最终的大小会小很多啊。

找到vs2008的VC目录,大致如下:

主要的目录如上图:

  • atlmfc:开发基于alt、mfc等所需要的头文件和导入库,可以不要
  • bin:vc的工具集,其中包含编译器、链接器、nmake等,当然要拉
  • crt:大概是vc运行时的源代码,可以不要
  • include:vc的头文件,当然要拉
  • lib:vc导入库,当然要拉
  • redist:crt运行时的动态连接库,建议带上,因为部署的时候需要

将上述需要的内容copy出来留用。另外,既然是windows编程,当然需要windows的导入库和头文件,来到Microsoft SDKs目录,找到6.0版本的SDK,其中的include和lib目录就是所需要的,偷出来吧!

 

继续瘦身

是不是发现怎么没有想象的那么小啊~。别急我们继续来瘦身,发现不管是vc的导入库还是windows的导入库都很大,其实原因就是每个导入库都对应不同的CPU架构有多个版本,并且除了x86之外,其余的导入库都单独放在独立的文件夹中,根据你的需要去掉其中不要的就好了。现在是不是大大缩小了。

别急,还有空间,看看bin下面,其中也有非x86的工具集,如果你在x86下工作,大可删掉其中其他平台的文件夹

还有还有,redist文件夹下面也包含有多个平台的动态连接库,取你所需即可,另外可以删掉mfc和atl的动态连接库。

 

制作命令行工具

上一步得到的200M左右的“编译环境”,可以发在U盘里面随身携带。不过如何使用呢?我们需要一个命令行工具,这个工具在启动时,会将我们这个编译环境相关的路径设置上,这样可以不与已经安装的高版本的vs产生冲突。

首先看下我的编译环境的目录结构

其中WinSDK6下分别是windows的include和lib,其他都是从上面的步骤中copy过来的,现在我们在制作vsvars32.bat:

@SET VCINSTALLDIR=J:\vs2008vcbuild
@SET FrameworkDir=C:\Windows\Microsoft.NET\Framework
@SET FrameworkVersion=v2.0.50727
@SET Framework35Version=v3.5
@if "%VCINSTALLDIR%"=="" goto error_no_VCINSTALLDIR

@echo Setting environment for using Microsoft Visual Studio 2008 x86 tools.


@rem
@rem Root of Visual Studio IDE installed files.
@rem

@set PATH=%VCINSTALLDIR%\bin;C:\Windows\Microsoft.NET\Framework\v3.5;C:\Windows\Microsoft.NET\Framework\v2.0.50727;%PATH%
@set INCLUDE=%VCINSTALLDIR%\include;%VCINSTALLDIR%\WinSDK6\Include;%INCLUDE%
@set LIB=%VCINSTALLDIR%\lib;%VCINSTALLDIR%\WinSDK6\Lib;%LIB%
@set LIBPATH=C:\Windows\Microsoft.NET\Framework\v3.5;C:\Windows\Microsoft.NET\Framework\v2.0.50727;%VCINSTALLDIR%\lib;%VCINSTALLDIR%\WinSDK6\Lib;%LIBPATH%

@goto end

:error_no_VCINSTALLDIR

    
[2]遇见C++ AMP:GPU的线程模型和内存模型
    来源:    发布时间: 2013-10-14

遇见C++ AMP:GPU的线程模型和内存模型

 

Written by Allen Lee

 

I don't care where the enemies are / Can't be stopped / All I know / Go hard
– Linkin Park, Lost In The Echo

 

C++ AMP、CUDA和OpenCL,选择哪个?

      在《遇见C++ AMP:在GPU上做并行计算》发布之后,我曾被多次问及为何选择C++ AMP,以及它与CUDA、OpenCL等相比有何优势,看来有必要在进入正题之前就这个问题发表一下看法了。

      在众多可以影响决策的因素之中,平台种类的支持和GPU种类的支持是两个非常重要的因素,它们联合起来足以直接否决某些选择。如果我们把这两个因素看作两个维度,可以把平面分成四个象限,C++ AMP、CUDA和OpenCL分别位于第二象限、第四象限和第一象限,如图1所示。如果你想通吃所有平台和所有GPU,OpenCL是目前唯一的选择,当然,你也需要为此承担相当的复杂性。CUDA是一个有趣的选择,紧贴最新的硬件技术、数量可观的行业应用和类库支持使之成为一个无法忽视的选择,但是,它只能用于NVIDIA的GPU极大地限制了它在商业应用上的采用,我想你不会为了运行我的应用特意把显卡换成NVIDIA的。C++ AMP的情况刚好相反,它适用于各种支持DirectX 11的GPU,但只能在Windows上运行。

图 1

      这些技术都有自己的特点和位置,你应该根据项目的具体情况选择合适的解决方案。如果你正在从事的工作需要进行大量计算,你想尽可能利用硬件特性对算法进行优化,而你的机器刚好有一块NVIDIA的显卡,并且你不需要在其他机器上重复执行这些计算,那么CUDA将是你的不二之选。尽管NVIDIA已经开源CUDA编译器,并且欢迎其他厂商通过CUDA编译器SDK添加新的语言/处理器,但AMD不太可能会为它提供在AMD的GPU上运行的扩展,毕竟它也有自己的基于OpenCL的AMD APP技术。如果你正在从事Windows应用程序的开发工作,熟悉C++和Visual Studio,并且希望借助GPU进一步提升应用程序的性能,那么C++ AMP将是你的不二之选。尽管微软已经开放C++ AMP规范,Intel的Dillon Sharlet也通过Shevlin Park项目验证了在Clang/LLVM上使用OpenCL实现C++ AMP是可行的,但这不是一个产品级别的商用编译器,Intel也没有宣布任何发布计划。如果你确实需要同时兼容Windows、Mac OS X和Linux等多个操作系统,并且需要同时支持NVIDIA和AMD的GPU,那么OpenCL将是你的不二之选。

 

GPU线程的执行

      在《遇见C++ AMP:在GPU上做并行计算》里,我们通过extent对象告诉parallel_for_each函数创建多少个GPU线程,那么,这些GPU线程又是如何组织、分配和执行的呢?

      首先,我们创建的GPU线程会被分组,分组的规格并不固定,但必须满足两个条件:对应的维度必须能被整除,分组的大小不能超过1024。假设我们的GPU线程是一维的,共8个,如图2所示,则可以选择每2个GPU线程为1组或者每4个GPU线程为1组,但不能选择每3个GPU线程为1组,因为剩下的2个GPU线程不足1组。

图 2

      假设我们创建的GPU线程是二维的,3 x 4,共12个,如图3所示,则可以选择3 x 1或者3 x 2作为分组的规格,但不能选择2 x 2作为分组的规格,因为剩下的4个GPU线程虽然满足分组的大小,但不满足分组的形状。每个分组必须完全相同,包括大小和形状。

图 3

      为了便于解释,我们的GPU线程只有寥寥数个,但真实案例的GPU线程往往是几十万甚至几百万个,这个时候,分组的规格会有大量选择,我们必须仔细判断它们是否满足条件。假设我们的GPU线程是640 x 480,那么16 x 48、32 x 16和32 x 32都可以选择,它们分别产生40 x 10、20 x 30和20 x 15个分组,但32 x 48不能选择,因为它的大小已经超过1024了。

      接着,这些分组会被分配到GPU的流多处理器(streaming multiprocessor),每个流多处理器根据资源的使用情况可能分得一组或多组GPU线程。在执行的过程中,同一组的GPU线程可以同步,不同组的GPU线程无法同步。你可能会觉得这种有限同步的做法会极大地限制GPU的作为,但正因为组与组之间是相互独立的,GPU才能随意决定这些分组的执行顺序。这有什么好处呢?假设低端的GPU每次只能同时执行2个分组,那么执行8个分组需要4个执行周期,假设高端的GPU每次可以同时执行4个分组,执行8个分组只需2个执行周期,如图4所示,这意味着我们写出来的程序具备可伸缩性,能够自动适应GPU的计算资源。

图 4

      说了这么多,是时候看看代码了。parallel_for_each函数有两种模式,一种是简单模式,我们通过extent对象告诉它创建多少GPU线程,C++ AMP负责对GPU线程进行分组,另一种是分组模式,我们通过tiled_extent对象告诉它创建多少GPU线程以及如何进行分组。创建tiled_extent对象非常简单,只需在现有的extent对象上调用tile方法,并告知分组的规格就行了,如代码1所示。值得提醒的是,分组的规格是通过模板参数告诉tile方法的,这意味着分组的规格必须在编译时确定下来,C++ AMP目前无法做到运行时动态分组。

代码 1

      既然C++ AMP不支持运行时动态分组,肯定会为简单模式预先定义一些分组的规格,那么C++ AMP又是如何确保它们能被整除?假设我们创建的GPU线程是一维的,共10000个,C++ AMP会选择每256个GPU线程为1组,把前面9984个GPU线程分成39个分组,然后补充240个GPU线程和剩下的16个GPU线程凑够1组,执行的时候会通过边界测试确保只有前10000个GPU线程执行我们的代码。对于二维和三维的情况,C++ AMP也会采取这种补充GPU线程的策略,只是分组的规格不同,必要时还会重新排列GPU线程,以便分组能够顺利完成。需要说明的是,简单模式背后采取的策略属于实现细节,在这里提及是为了满足部分读者的好奇心,你的算法不该对它有所依赖。

 

共享内存的访问

      既然简单模式可以自动分组,为何还要大费周章使用分组模式?为了回答这个问题,我们先要了解一下GPU的内存模型。在Kernel里,我们可以访问全局内存、共享内存和寄存器,如图5所示。当我们通过array_view对象把数据从主机内存复制到显卡内存时,这些数据会被保存在全局内存,直到应用程序退出,所有GPU线程都能访问全局内存,不过访问速度很慢,大概需要1000个GPU时钟周期,大量的GPU线程反复执行这种高延迟的操作将会导致GPU计算资源的闲置,从而降低整体的计算性能。


    
[3]统计元素个数-list妙用
    来源:    发布时间: 2013-10-14
在python俱乐部里,看到的一个用法,觉得不错,收下了。
#encoding:utf8

mylist = [2,2,2,22,2,2,3,3,3]
myset = set(mylist)

for item in myset:
    print mylist.count(item),"of",item,"in list"


SunRise_at 2013-01-10 16:00 发表评论

    
最新技术文章:
▪C++单例模式应用实例
▪C++设计模式之迭代器模式
▪C++实现动态分配const对象实例
▪C++设计模式之中介者模式
▪C++设计模式之备忘录模式
▪C++插入排序算法实例
操作系统 iis7站长之家
▪C++选择排序算法实例
▪C++归并排序算法实例
▪C++设计模式之观察者模式
▪C++中复制构造函数和重载赋值操作符总结
▪C++设计模式之状态模式
▪C++设计模式之策略模式
▪C++设计模式之访问者模式
▪C++设计模式之模板方法模式
▪C++实现下载的代码
▪C++模板之特化与偏特化详解
▪C++实现查壳程序代码实例
▪C语言、C++内存对齐问题详解
▪C语言、C++中的union用法总结
▪C++基于CreateToolhelp32Snapshot获取系统进程实例
▪C++中memcpy和memmove的区别总结
▪C++通过TerminateProess结束进程实例
▪C++内存查找实例
▪C++实现CreatThread函数主线程与工作线程交互的...
▪C++设计模式之桥接模式
▪C++中关键字Struct和Class的区别
▪C++设计模式之组合模式
▪C++ COM编程之什么是组件?
▪C++ COM编程之什么是接口?
 


站内导航:


特别声明:169IT网站部分信息来自互联网,如果侵犯您的权利,请及时告知,本站将立即删除!

©2012-2021,,E-mail:www_#163.com(请将#改为@)

浙ICP备11055608号-3