分类 开发技术 下的文章

Windows 7中系统服务进程无法使用cuda进行GPU并行计算的解决方案

最近测试提了一个Bug,原来一直正常的服务进程在新的系统中无法正常工作,现象就是显卡GPU没有正常工作。

这两天跟踪了一下问题,找到了原因,这里把具体的解决办法贴出来,方便有同样问题的朋友快速解决问题^_^。

原因分析:
Vista之后,操作系统引入了Session 0 Isolation的机制,将系统服务全部隔离到会话0中执行,但是会话0中的系统服务无法使用显卡设备,导致cuda在加载显卡驱动时失败,而无法启动GPU进行并行计算。

具体的会话0隔离机制可以参考MSDN文章:
http://msdn.microsoft.com/en-us/library/bb756986.aspx

解决方案:
找到了原因一切就好办了,从分析来看,主要是会话0中无法加载显卡驱动,所以这里需要将使用显卡的进程越狱到用户会话中,比如会话1等。

这个办法在CUDA的论坛中已经有过讨论了,这里有兄台给出了一些示例代码,可以参考:
http://forums.nvidia.com/index.php?showtopic=93450

这里说说我的具体解决方案:

  1. 在服务进程中,循环枚举可用用户会话ID
  2. 获取有效用户会话之后,获取对应用户的会话令牌
  3. 以该用户会话启动新的进程

涉及到的API如下:
通过WTSEnumerateSessions 获取所有有效会话,通过判断WTS_SESSION_INFO的State字段,获取活动会话ID
记得使用完之后,通过WTSFreeMemory释放相关内存
通过WTSQueryUserToken获取会话ID对应的会话Token
最后调用CreateProcessAsUser将进程启动到用户会话中,就可以了

总结:
其实上面的方法,相当于是延时启动,当有用户登陆之后,才启动真正的工作进程。
上述方案,需要对工程进行进程分离,将实际工作的进程独立起来,以启动到用户会话中。
有一个小问题,目前没有找到相关解决方案,有待进一步学习,有知道的朋友请分享一下^_^:
当开启UAC功能时,通过CreateProcessAsUser启动的进程无法获取管理员权限,如果工作进程需要管理员权限,可能需要关闭UAC功能才行。

Fedora 13下源码编译Mono和MonoDevelop流程总结

Fedora提供的RPM版的Mono版本比较低,为了学习体验最新版,就自己编译了一遍,整体流程比较简单,这里做个笔记记录一下。其他的一些插件就根据需要自行安装吧,走完这个流程,其他的就是小意思啦。

以下安装的版本为目前最新版(2011.5.21) Mono 2.10.2 和 MonoDevelop 2.4.2

需要下载的文件列表如下:

  • Mono运行时:mono-2.10.2.tar.bz2
  • GTK Bind:gtk-sharp-2.12.10.tar.bz2
  • GNOME Bind:gnome-sharp-2.24.1.tar.bz2
  • Mono Addins:mono-addins-0.6.1.tar.bz2
  • GDI+的Linux移植版本:libgdiplus-2.10.tar.bz2
  • MonoDevelop:monodevelop-2.4.2.tar.bz2

可以从这里进行下载:
http://ftp.novell.com/pub/mono/sources/

  1. 安装Mono运行时
tar -xvf mono-2.10.2.tar.bz2
cd mono-2.10.2
./configure --prefix=/usr
make 
make install

整个过程应该不存在大的问题

  1. 由于MonoDevelop需要其他的一些依赖库,这些库在系统中没有默认安装,Mono运行时也没有直接提供,所以这里要手动安装

安装GDI+

tar -xvf libgdiplus-2.10.tar.bz2
cd libgdiplus-2.10
./configure --prefix=/usr
make
make install
  1. 安装GTK Bind
tar -xvf gtk-sharp-2.12.10.tar.bz2
cd gtk-sharp-2.12.10
./configure --prefix=/usr
make 
make install
  1. 安装GNOME Bind

安装目前版本的GNOME Bind的时候,由于版本更新有些不同步,所以直接编译会出现Mono.GetOptions.dll找不到的错误提示,这里需要注意修正以下Makefile文件

tar -xvf gnome-sharp-2.24.1.tar.bz2
cd gnome-sharp-2.24一 
./configure --prefix=/usr

Makefile文件生成之后,这里需要修改sample相关文件的Makefile

由于这里的Mono.GetOptions.dll被开发组重命名为Mono.Options.dll,但是GNOME Bind包还没有及时更新,所以回会出现找不到该dll的问题,考虑到该dll只是在测试程序TestXfer.exe中使用,影响不大,所以这里直接注释掉TestXfer.exe的生成和运行即可。

进入子目录sample/gnomevfs,打开其中的Makefile文件,将如下几行注释掉就可以了:

注释掉221行:

EXTRA_TARGET = TestXfer.exe

注释掉449和450行:

TestXfer.exe: $(srcdir)/TestXfer.cs $(assemblies)

$(CSC) /out:TestXfer.exe $(references) -r:Mono.GetOptions.dll $(srcdir)/TestXfer.cs

然后退出子目录,进入到父目录gtk-sharp-2.12.10,继续执行:

make
make install
  1. 安装Mono Addins
tar -xvf mono-addins-0.6.1.tar.bz2
cd mono-addins-0.6.1
./configure --prefix=/usr
make
make install
  1. 安装完成相关依赖之后,就可以开始安装Monoevelop了
tar -xvf monodevelop-2.4.2.tar.bz2
cd monodevelop-2.4.2
./configure --prefix=/usr
make 
make install

截张图过来:
1.png

(转)Windows 7 下无法使用DevPartner BoundsChecker 9.1进行调试的问题

问题描述如下:

点击Start with Error Detection时回出现错误提示,显示无法打开dpinjsvc服务

进一步的错误提示如下:

CRunManager::InjectNow() - BCAX::StartRecording() FAILED: hr = 0x80004005

解决方法:

添加localhost到127.0.0.1的本地DNS映射

在%WinDir%/System32/Drivers/Etc目录中,编辑hosts文件,在末尾添加两行

127.0.0.1 localhost

::1 localhost

然后重新启动计算机即可

这是官方给出的解决方案,经测试,能够解决问题,看来BoundsChecker的机制也是基于远程调试的。。。

(转)程序出错后,程序员给测试人员的20条高频回复

呵呵,开发和测试的暗战

编者按:程序员和软件测试员之间的关系无须多言。这些经典回复是国外程序员总结分享的,“全球通用”。
  20. "That’s weird…" 很奇怪……
  19. "It’s never done that before." 以前没这样过的。
  18. "It worked yesterday." 昨天还好好的。
17. "How is that possible?" 那怎么可能?(怎么会出问题?)
  16. "It must be a hardware problem." 这一定是硬件问题。
  15. "What did you type in wrong to get it to crash?" 你输入什么东西后才崩溃的?
  14. "There is something funky in your data." 你的数据有问题。
  13. "I haven’t touched that module in weeks!" 我好几个礼拜没动那个程序了!
  12. "You must have the wrong version." 你一定在用错误的版本。
  11. "It’s just some unlucky coincidence." 这只是凑巧。
  10. "I can’t test everything!" 我无法测试所有东西。(我的机器环境下,无法测试所有的可能情况。)
  09. "THIS can’t be the source of THAT." “这”不可能是问题的原因。
  08. "It works, but it hasn’t been tested." 程序能用,不过还没有测试。
  07. "Somebody must have changed my code." 一定有人改了我的代码。
  06. "Did you check for a virus on your system?" 你的电脑扫描病毒了么?
  05. "Even though it doesn’t work, how does it feel? 即便程序不行了,(你觉得)程序写得如何?
  04. "You can’t use that version on your system." 你不能在你系统上使用那个版本的程序。(程序版本和系统有冲突。)
  03. "Why do you want to do it that way?" 你怎么会想着那样操作啊?
  02. "Where were you when the program blew up?" 程序崩溃时,你在做什么呢?(做了哪些操作?)
  01. "It works on my machine" 在我机器上好好的!!!(潜台词:怎么在你那就出问题了呢!!!)

  编者后话

  虽然已经远离编程,但经常还是会用到第20、19条,当然也不会“错过”第1条。各位看过之后,不知你都用上了哪几条哦~

(转)C++为什么不用delete代替delete[]?

总结:一直想不通c++为什么多此一举,呵呵,前几天给Bjarne Stroustrup大师写了一份信,第二天就收到回复了,自己再仔细琢磨了一下,终于好像弄明白了:-)

我的理解是这样的,无论new还是new[ ],C++的确知道返回的这个指针它指向多大的内存块,否则它就不可能正确地释放掉这块内存了。但是delete需要知道的不仅仅是指针指向多大的内存,而更重要的是要知道指针指向的数组中有多少个对象,知道了对象数量才能依次一一调用它们的析构函数。那么,下面的代码会产生什么样的结果??

int * pArray = new int[100];

……

delete pArray; //本来应该是 delete [ ] pArray;

根据上面的解释,我们不难想象,上述代码错误的原因并不是因为它只释放掉第一个元素的空间而没有能完全释放整个pArray所指的内存。 也就是说,在内存释放上不存在问题。问题出在在这里只对第一个元素调用了析构函数,而其他99个元素并没有被妥善地析构掉。呵呵,这才是真正的问题所在!! 当然对于整数类型来说并不会导致什么问题,但假如在每个对象中都分配了额外的资源,那么不调用对象的析构函数可就会导致严重的后果了……

那使用delete[ ]有什么用?这要从new[ ]说起,在new一个数组时,编译器会悄悄地在内存中保存一个整数用来表示数组中元素的个数。这样在使用delete[ ]时,编译器就会生成读取这个整数的代码,然后逐个调用析构函数。如果使用delete,则编译器只当作指针所指的是单个对象。再说了,new单个对象时,编译器也不会悄悄记录数组中元素的个数。呵呵,从这也可以感觉出C++的设计风格和宗旨,决不多费一点手脚,单个对象我就不记录长度,只有是数组时我才记录!:-)

下面是我给Bjarne Stroustrup的邮件及他的回信。在此对Bjarne Stroustrup大师平易近人的风范再次表示钦佩!!

Hi, Dr. Stroustrup

Firstly,Thank you for your great invention, the c++ programming language is
really a great job, it gives me a lot of help in my study, it makes my work much
more convenient!

Thanks

Well, today ,I run into a confused problem about delete and delete[], so I
wonder if you could give me some explanation or tips. I simply can't understand
why c++ don't treat them in the same way. In other words, I think there is no
need for delete[].

For example, "delete [] ps", many textbooks just say that the operator
delete[] is used to tell the compiler that the pointer "ps" refers to an array,
but not a single object. Of course, I know that, but the thing is that I think
the c++ compiler is totally clever enough to figure out whether "ps" points to a
single object or an array. There is no need to bother the programmer to point it
out explicitly.

No. The compiler cannot know.

void f(int* p)
{
delete p; // or maybe delete [] p?
}

void g()
{
int* q = new int[70];
f(q);
q = new int;;
f(q);
}

separately compile those two functions an the compiler had no way of
knowing how many ints p points to.

It's no doubt that the compiler knows the size of storage to which is pointed
by "ps". Otherwise, it's impossible for c++ to deallocate the memory properly.
OK, now that the compiler exactly knows how many bytes is allocated there and
which type the object is, it can compute how many object are there, I mean,
" number of object = number of bytes allocated / sizeof(object type) "
Ok, after that, c++ may call destructor iteratively to destroy each object in
the array and then deallocates the memory.

It is a bit trickier than that. Many allocators allocates space for at
least N ints when you ask for new int[N]. It is not uncommon for an
allocator to allocate more to minimize fragmentation.

I don't know if I have made my question clear:-) In conclusion, I think a
single object is just a special case of an array, so c++ is supposed to deal
with them in the same way. There is no need for us to differentiate delete and
delete[].

The snag is that many allocators (at least traditionally) just keep
track of the number of bytes allocated (rounding the allocation up to
something convenient). With destructors, the compiler has to know how
many objects are there (not just how much space is allocated). Some
implementers use (or used) two different layouts for individual objects
and arrays - the array layout (only) included an object count.

In fact, I know certainly this is my misunderstanding. if not that, the c++
committe should have changed the c++ syntax:-) I just hope to get some
convincing explanation.

Thank you, really appreciate for your help!

Supermonkey,China,Nankai University
2007-09-03