nifeng

welcome!

RSS Feed

welcome to my blog

在MFC调用CUDA

0 Comments

已经是三月份了,想到毕设一个字还没写,顿时感觉到压力有点小大,其实重点是程序还没有搞出来。毕设的主要内容就是把ICA算法用CUDA并行实现一下,由于原来的系统是基于MFC的,这样就涉及到在MFC当中调用CUDA程序的问题,查阅了一下资料,顺便记录一下,其实主要涉及的是在VS这个集成的开发环境中如何自己设定编译器和编译规则的问题。

  1. 修改文件的编译链接设置

    1. 打开相应文件的属性设置窗口:
    2. 修改General中的Tool为Custom Build Tool(即为自定义生成工具),也就是自己指定编译器和生成规则,设置完毕后关闭属性窗口,再打开发现General底下的属性已经变成了Custom Build Step.
    3. 在Custome Build Step中需要设置Command Line和Outputs,如果存在编译依赖项也是需要设置Additional Dependencies的(视情况而定)。我这里的Command Line和Outputs设置如下(我的文件名为kernelIter.cu,具体的文件位置要根据自己的实际情况。如果你安装了CUDA程序生成向导,可以把生成向导生成的CUDA程序的Command Line拷贝过来,然后把文件名和位置替换下即可):
      • Command Line:

        "D:\program\cuda\toolkit\bin\nvcc.exe" -arch sm_10 -ccbin "C:\Program Files\Microsoft Visual Studio 9.0\VC\bin" -Xcompiler "/EHsc /W3 /nologo /Od /Zi /RTC1 /MTd " -I"D:\program\cuda\toolkit\include" -I"D:\program\cuda\NVIDIA GPU Computing SDK\C\common\inc" -maxrregcount=32 --compile -o "Release\kernelIter.cu.obj" "D:\研究生\毕设\project\ICA2011年5月13日\kernelIter.cu"
      • Outputs:

        $(IntDir)/$(InputName).cu.obj
  2. 修改工程的编译链接设置(最好参考CUDA程序生成向导生成的CUDA程序,照着修改即可)

    1. 工程文件Property Pages->Configuration Properties->Linker->General
    2. 工程文件Property Pages->Configuration Properties->Linker->Input

总结,由于VS这个集成开发环境帮我们做了许多工作,所以借助于它进行开发时,我们对编译环境,依赖项等进行设置,为我们带来了许多便利,但是也致使我们对整个程序从源代码编写到编译到执行缺少足够的认识,所以有时候摆脱集成开发环境的束缚,一切从命令行开始还是很有必要的。

Filed under CUDA

WEB开发中的cookie和session

0 Comments

WEB开发中,cookie和session是两个比较重要的概念。不过在谈这两个概念之前,我们先来聊一聊HTTP协议,首先翻一翻教科书,书上是这么说的:“Http协议定义了浏览器怎么样向万维网服务器请求万维网文档以及服务器怎样把文档传送给浏览器。Http协议规定在Http客户与Http服务器之间的每次交互,都是由一个ASCII码串构成的请求和一个类MIME(MIME-like)的响应组成。Http报文通常都是使用TCP连接传送。但是HTTP协议本身是无连接的。这就是说,虽然HTTP协议使用了TCP连接,但通信的双方在交换HTTP报文之前,不需要先建立HTTP连接。HTTP协议是无状态的。”(这边对HTTP协议不做详细的解释了,因为自己懂得也不是特别透彻,等下次学习后再写一篇来记录下。)这边对 cookie和session最相关的一点就是HTTP协议是无状态的,也就是即使是一个页面用户的第二次访问服务器并不知晓,HTTP并不记录用户的访问状态。这里你可以会吐槽下HTTP协议了,但是当初这么设计也是有原因的,因为这种无状态特性简化了服务器的设计,使得服务器更容易支持大量并发的HTTP请求。既然HTTP协议本身不支持这种状态记录的功能,那就只能通过其它办法了。很显然,其中一个解决的办法就是就是在第一次访问时,我们将些状态信息记录下来放在客户端,下次再访问该页面(或者应用时)将这些信息发送给服务器,这样服务器就知道:哦,这个人曾经访问过。这样的话,服务器可以根据这些信息进行做出不同的响应。而cookie指的就是客户端的相关信息,session则是服务器的相关信息。更加专业的一种说法就是cookie机制采用的是在客户端保持状态的方案,而session机制采用的是在服务器端保持状态的方案。

首先我们来说说cookie。正统的cookie分发是通过扩展HTTP协议来实现的,服务器通过在HTTP的响应头中加上一行特殊的指示以提示浏览器按照指示生成相应的cookie。然而纯粹的客户端脚本如JavaScript或者VBScript也可以生成cookie。(这个还没有研究过,估计利用这个功能制造一些攻击什么的。)而cookie的使用是由浏览器按照一定的原则在后台自动发送给服务器的。浏览器检查所有存储的cookie,如果某个cookie所声明的作用范围大于等于将要请求的资源所在的位置,则把该cookie附在请求资源的HTTP请求头上发送给服务器。也就是在HTTP头上指定生成cookie,之后的行为方法很大都是取决浏览器,比如如果是持久cookie(下面会提到说明什么是持久cookie),文件的名称,存放的位置,以及下次按照怎样的规则,如何把这些信息传送到服务器端都是由浏览器来决定和执行的。

cookie的内容主要包括:名字,值,过期时间,路径和域。路径与域一起构成cookie的作用范围。若不设置过期时间,则表示这个cookie的生命期为浏览器会话期间,关闭浏览器窗口,cookie就消失。这种生命期为浏览器会话期的cookie被称为会话cookie。会话cookie一般不存储在硬盘上而是保存在内存里,当然这种行为并不是规范规定的。若设置了过期时间,浏览器就会把cookie保存到硬盘上,关闭后再次打开浏览器,这些cookie仍然有效直到超过设定的过期时间。

我们再来看一看session机制。session通常采种散列表(key-value)这种数据结构保存在服务器端,通过sessionID来标识不同的会话。当程序需要为某个客户端的请求创建一个session时,服务器首先检查这个客户端的请求里是否已包含了一个sessionID,如果已包含则说明以前已经为此客户端创建过session,服务器就按照sessionID把这个session检索出来使用(检索不到,会新建一个),如果客户端请求不包含sessionID,则为此客户端创建一个session并且生成一个与此session相关联的sessionID,sessionID的值应该是一个既不会重复,又不容易被找到规律以仿造的字符串,这个sessionID将被在本次响应中返回给客户端保存。保存这个sessionID的方式可以采用cookie,这样在交互过程中浏览器可以自动的按照规则把这个标识发送给服务器。一般这个cookie的名字都是类似于SEEESIONID。但cookie可以被人为的禁止,则必须有其他机制以便在cookie被禁止时仍然能够把session id传递回服务器。经常被使用的一种技术叫做URL重写,就是把sessionID直接附加在URL路径的后面。还有一种技术叫做表单隐藏字段,就是服务器会自动修改表单,添加一个隐藏字段,以便在表单提交时能够把sessionID传递回服务器。实际上这种技术可以简单的用对action应用URL重写来代替。

和cookie一样,session的具体存储方式完全取决于服务器端,可以将其写入文件,或者就一直置于内存中。在php中想要使用session的话,需要注意php.ini中的配置项,最主要的是session.save_handler和session.save_path这两个,一个指定了存储会话的方式,比如可以是files,redis等,另一个指定了存储的位置。除了直接查看php.ini外,可以使用phpinfo()函数来查看。另外session也是有失效时间的,这是必须的设置,因为为了保持状态,session通常是在用户在点击logout时才去删除session,但是并不能保证用户在离开时都会点击logout来删除会话,所以session需要设置失效时间来避免这种情况。所以有时候当你登陆一个网站后,很长时间没有操作后再想操作时,发现需要重新登陆。

简单总结下session和cookie的相同之处和区别,相同之外:

  1. 为了维持状态,提供了多次访问之间的信息共享
  2. 都有失效时间

区别:

  1. session处于服务器端,cookie处于客户端,很多应用场景下是通过sessionID来结合使用的
  2. 注意会话cookie和session的区别,用户关闭浏览器的话,会话cookie会消失,但是session仍在服务器端,除非手动删除或者超时
Filed under lamp

有序矩阵查找给定的值

0 Comments

一个矩阵,每一行的元素,从左到右保持严格递增,每一列的元素,从上到下保持严格递增。(矩阵中的每一个元素都不相同)

分析:首先想到的是就是二分查找,但是这里需要注意的是在一维空间中,二分查找总是将待查找的空间一分为二,而在二维空间中,总是一分为四。假设矩阵最左上角的点为begRow,begCol,最右下角的点为endRow,endCol,那么我们需要考查的点是midRow=begRow+(endRow-begRow)/2, midCol=begCol+(endCol-begCol)/2,这个点将将空间分为四个部分。我们分别用左上角的点和右下角的点来表示该空间。

当查找元素<matrix[midRow][midCol]时,lucky~~搜索成功。

当查找元素<matrix[midRow][midCol]时,空间被分为空间1{(begRow,begCol),(midRow,midCol)} 空间2{(begRow,midCol+1),(midRow-1,endCol)} 空间3{(midRow+1,begCol),(endRow,midCol-1)}和空间4{(midRow,midCol),(endRow,endCol)},其中空间1,空间2,空间3 是我们进行递归搜索的空间。

当查找元素>matrix[midRow][midCol]时,空间被分为空间1{(begRow,begCol),(midRow,midCol)} 空间2{(begRow,midCol+1),(midRow,endCol)} 空间3{(midRow+1,begCol),(endRow,midCol)}和空间4{(midRow+1,midCol+1),(endRow,endCol)},其中空间2,空间3,空间4 是我们进行递归搜索的空间。

大体思路就是这样,由于是采用递归,所以必须有返回的条件或者限制啥时候开始递归,另外可以增加一引起剪枝的方法,提高算法实际执行的效率。时间复杂度T(n)=3*T(n/4)+O(1),计算这种时间复杂度有个什么定理的,忘了。。。囧。回头补上。

(更新:利用主定理,时间复杂度为O(n^log4 3))

程序的代码如下:

1 #include <iostream>
2 using namespace std;
3
4 int matrix[4][4]={{1,4,7,9},{2,5,8,10},{3,6,11,12},{13,14,15,16}};
5 //int matrix[1][1]={{1}};
6 int posRow=-1;
7 int posCol=-1;
8
9 bool find(int begRow,int begCol,int endRow,int endCol,int data){
10     if(begRow>endRow || begCol>endCol)
11         return false;
12
13     if(begRow==endRow && begCol==endCol) {
14         if (matrix[begRow][begCol]==data)
15         {
16             posRow=begRow;
17             posCol=begCol;
18             return true;
19         }
20         else
21             return false;
22     }
23     if (data>matrix[endRow][endCol] || data<matrix[begRow][begCol])
24         return false;
25
26     int midRow=begRow+(endRow-begRow)/2;
27     int midCol=begCol+(endCol-begCol)/2;
28
29     if (matrix[midRow][midCol]==data)
30     {
31         posRow=midRow;
32         posCol=midCol;
33         return true;
34     }
35     else if (matrix[midRow][midCol]>data) {
36         return find(begRow,begCol,midRow,midCol,data)
37             || find(begRow,midCol+1,midRow-1,endCol,data)
38             || find(midRow+1,begCol,endRow,midCol-1,data);
39     }
40     else {
41         return find(midRow+1,midCol+1,endRow,endCol,data)
42             || find(begRow,midCol+1,midRow,endCol,data)
43             || find(midRow+1,begCol,endRow,midCol,data);
44     }
45 }
46
47 int main(int argc,char* argv[]){
48     if (find(0,0,3,3,11))
49     {
50         cout<<posRow<<’\t’<<posCol<<endl;
51     }
52     return 0;
53 }

经过硕哥的提点(硕哥V5),该问题还有更优的解法,更优的解法的时间复杂度为O(M+N),M和N分别为矩阵的行和列。具体的算法如下:

从矩阵的左下角开始找起,如果当前的元素比查找的元素大的话,则向上走,如果当前的元素比查找的元素小的话,则向右走。