在VS中使用CUDA时的一些注意事项

1. 尽量不要将__host__函数与(__device__以及__globle__)函数放在同一个文件中,否则调试时会出现当前statement指针错行的问题。(bug?)

2. 如何解决VS中无法使用NSight同时对GPU和CPU代码设置断点进行调试的问题。

Thinkpad R400第三方六芯电池损耗记录

第三方六芯电池设计容量:56.16瓦小时。

循环周期数   完全充电容量(瓦小时) 日期

3                           52.**                                  2014-03-01

4                          51.98                                  2014-03-03

5                          51.98                                  2014-03-04

6                          51.41                                  2014-03-13

8                          51.31                                  2014-03-21

9                          50.74                                2014-04-03

10                       50.18                                2014-05-09

11                       49.62                                2014-05-27

13                       47.56                                2014-05-27

16                       46.01                                2014-10-15

20                       44.47                                2014-12-09

21                       42.66                                2015-01-07

修复更换SIM导致的MIUI网络短信无法使用的问题

MIUI手机ROM提供了一项很不错的功能,即网路短信(Web Message),同时启用了该功能的MIUI用户之间在网络畅通的情况下可以相互发送免费短信息。

不过在该功能发布以来很多用户遭遇了和我相同的问题:在更换手机SIM卡之后,网络短信功能无法激活,且换回之前的SIM卡同样无法激活,显示“服务器IO错误”或者“无法从服务器获取本机号码”等等。

在遇到这个问题之后,我在网络上查找、尝试了各种解决方法。功夫不负有心人!终于,其中的一种方法解决了问题。年纪大了。。该方法的出处已经记不清了,只能把步骤写下来,给该遇到这个问题的其他人作为参考。

步骤:

1. 将首次成功激活使用的SIM卡装入手机中。

2. 重启手机,进入小米Recovery,清空缓存数据和用户数据。

3. 重启手机,进入系统,按照系统提示,在保证网络畅通的情况下登陆之前的小米账号,并选择同步数据及启用网络短信。

4. 完成设置后,进入账号设置查看小米帐户,可以发现,网络短信已经成功开启了。

5. 如果打算使用不同的SIM卡,可以在小米帐户设置中,关闭所有同步内容,并关闭网络短信,最后注销小米帐户。

6. 完成上一步后,关机,更换SIM卡。

7. 开机进入系统,在帐户设置中,重新添加小米帐户,并选择同步数据、开启网络短信。设置完成后可以发现,网络短信成功开启了。

PS:我的手机为2S,,其他的手机未做测试。

如何解决Thinpad Mobile Hotpots虚拟无线无法使用的问题

Thinkpad自带的Access Connections (AC)软件可以用来方便的管理计算机的网络连接,为不同的网络提供了丰富的自定义设置,如设置默认打印机、自动设置代理、启用VPN等等。

此外使用AC自带的Mobile Hotspots功能还可以方便地设置虚拟无线,将已连接的有线或者网线网络共享给其他移动设备使用。

不过在实验室中使用时中碰到一个奇怪的问题,自己的手机可以连接创建的虚拟无线但无法上网。在测试过程中发现浏览器无法显示网页,但QQ等软件确可以正常使用。这可是好兆头,看来应该是域名解析的问题了。马上查看了Thinkpad的网络适配器设置,建立的虚拟无线适配器的设置中DNS一栏为空。将DNS设置为google dns后,问题果然解决了。

现在的疑问是上述问题在家中使用时并未出现,是学校默认DNS设置的问题?以后有机会在好好测试下吧。

——————————————

updated on 2014-02-27

后续使用中发现问题依旧,如果下载文件马上就会出现问题。这真是诡异的现象,只好暂时使用Intel驱动自带的MyWiFi功能了。

——————————————

updated on 2014-02-28

1. 更新Acecess Connections到6.20

2. 连接网络,保存位置概要。

3. 在当前连接的位置概要文件高级设置的网络安全中将“禁用因特网连接共享”和“启用Windows防火前”两项的默认勾选取消。

4. 启用Mpbile Hotspots,设置密码。

经测试暂时可用,未对老版本AC进行测试。猜测问题可能在于AC版本,也可能在于默认位置概要中的网络设置。

updated last

因为启用了gae proxy?

 

指针与const限定符


(1) 指向const对象的指针(常量指针)

// 常量指针的两种形式
const int *ptr; // 推荐
int const *ptr;

C++强制指向const对象的指针必须具有const特性。此处const限定的了ptr指针所指向的对象的类型,而不是ptr指针本身。如果有需要,可以给指向const对象的指针重新赋值,使其指向另一个const对象;但不能通过该指针修改其指向的对象的值。

(2) const指针(指针常量)

double *const ptr;


指针本身的值不能改变,必须在定义时初始化。
(3) 指向const对象的const指针>

const int *const ptr;

栈(stack):后入先出(LIFO),有入栈Push、出栈Pop等操作。


一个简单的栈(Stack)实现(基于数组):

#pragma once
#include 
#include 

using namespace std;

template 
class MyStack
{
public:
	MyStack(void) : top(-1) {}
	~MyStack(void) {}

	void Push(const T &data);
	const T& Pop();

	int GetStackSize() {return stackSize;}
	void Output();	// 输出栈中数据(测试用)

private:

	int top;	// 栈顶
	T S[stackSize];	// 栈缓冲区

};

template 
void MyStack::Push(const T &data)
{
	assert(top < GetStackSize()-1);	// 防止栈上溢

	top++;
	S[top] = data;
}

template 
const T& MyStack::Pop()
{
	assert(top>=0);	// 防止栈下溢

	return S[top--];
}

template 
void MyStack::Output()
{
	for (int i=0; i<=top; ++i )
	{
		cout << S[i] << " ";
	}
	cout << endl;
}


测试代码:

#include "stdafx.h"
#include "MyStack.h"

int _tmain(int argc, _TCHAR* argv[])
{
	MyStack stack;

	stack.Push(2);
	stack.Push(1);
	stack.Push(5);
	stack.Push(10);
	stack.Output();

	stack.Pop();
	stack.Pop();
	stack.Pop();
	stack.Output();

	stack.Push(7);
	stack.Push(9);
	stack.Pop();
	stack.Output();

	return 0;
}


二叉查找树


二叉查找树(Binary Search Tree):

二叉查找树是一种特殊的二叉树。树中的每一个节点都父节点,左子节点,右子节点。左子节点小于等于该节点,右子节点大于等于该节点。

二叉查找树包含Search, Minimum, Maximum, Predecessor(前趋), Successor(后续), Insert, Delete等操作。这些操作的时间复杂度均为$$O(h)$$,其中h为树的高度。

二叉查找树实现代码(部分功能):

// BinarySearchTree.h
#pragma once
#include 

using namespace std;

template  class BinarySearchTree;

// 树的节点
template 
class TreeNode
{
	friend BinarySearchTree;
public:
	TreeNode(){data = 0; parent = 0; left = 0; right = 0;};
	TreeNode(T value) {data = value; parent = 0; left = 0; right = 0;}
private:
	T data;	
	TreeNode* parent;
	TreeNode* left;
	TreeNode* right;	
};

// 二叉查找树
template 
class BinarySearchTree
{
public:
	BinarySearchTree(void) {root = 0;}
	BinarySearchTree(T* dataArray, int count)	// 使用数组构造二叉查找树
	~BinarySearchTree(void) { }

	void InOrderTreeWalk();
	void Insert(T value);
	void Delete(T value);
	int MaxValue();	// 函数返回值:0-找到最大值 -1-未找到最大值(空树)
	int MinValue();	// 函数返回值:0-找到最小值 -1-未找到最小值(空树)
	int Successor(T value);	// 返回值为0/-1,表示是否找到
	int Predecessor(T value); // 返回值为0/-1,表示是否找到

private:
	void InOrderTreeWalk(TreeNode *node);			// 按顺序输出树中的所有数据
	TreeNode* Search(T target, TreeNode *node);	// 在树中查找给定的某个关键字对应的节点
	TreeNode* Search(T target);
	TreeNode* Minimum(TreeNode *node);			// 查询树中关键字最小的节点	
	TreeNode* Maximum(TreeNode *node);			// 查找树中关键字最大的节点
	TreeNode* Successor(TreeNode *node);			// 返回指定节点的后继节点
	TreeNode* Predecessor(TreeNode *node);		// 返回指定节点的前趋节点
	void Insert(TreeNode *node);						// 插入新节点
	TreeNode* Delete(TreeNode *node);				// 删除指定节点

private:
	TreeNode *root;
};

template 
BinarySearchTree::BinarySearchTree(T* dataArray, int count)
{
	root = 0;
	for (int i=0; i<count; ++i)
	{
		Insert(dataArray[i]);
	}
		
}

template 
void BinarySearchTree::InOrderTreeWalk()
{
	InOrderTreeWalk(root);
	cout << endl;
}

template 
void BinarySearchTree::Insert(T value)
{
	TreeNode* newNode = new TreeNode(value);
	Insert(newNode);
}

template 
void BinarySearchTree::Delete(T value)
{
	TreeNode* delNode = Search(value);
	if (delNode != 0)
		Delete(delNode);
}

template 
int BinarySearchTree::MaxValue()
{
	if (root == 0)
	{
		cout << "The tree is empty." << endl;
		return -1;
	}

	cout << "The max value is " << Maximum(root)->data << endl; // 输出最大值

	return 0;
}

template 
int BinarySearchTree::MinValue()
{
	if (root == 0)
	{
		cout << "The tree is empty." << endl;
		return -1;
	}

	cout << "The min value is " << Minimum(root)->data << endl; // 输出最大值

	return 0;
}

template 
int BinarySearchTree::Successor(T value)
{
	TreeNode* node = Search(value);
	TreeNode* successor = 0;

	if (node == 0)	// 输入value在树中不存在
	{
		cout << value << " is not exit in tree." << endl;
		return -1;
	}

	successor = Successor(node);
	if (successor == 0)
	{
		cout << "There is no successor of " << value << " in the tree." << endl;
		return -1;
	}
	else
		cout << "The successor of "<< value << " is " << successor->data << endl;

	return 0;
}

template 
int BinarySearchTree::Predecessor(T value)
{
	TreeNode* node = Search(value);
	TreeNode* predecessor = 0;

	if (node==0)
	{
		cout << value <<" is not exit in the tree." << endl;
		return -1;
	}

	predecessor = Predecessor(node);
	if (predecessor == 0)
	{
		cout << "There is no predecessor of " << value << " in the tree." << endl;
		return -1;
	}
	else
		cout << "The predecessor of " << value << " is " << predecessor->data << endl;

	return 0;
}


template 
void BinarySearchTree::InOrderTreeWalk(TreeNode *node)
{
	if (node == 0)
		return;
	else 
	{
		InOrderTreeWalk(node->left);
		cout << node->data << " ";
		InOrderTreeWalk(node->right);
	}
}


template 
TreeNode* BinarySearchTree::Search(T target)
{
	return Search(target, root);
}

template 
TreeNode* BinarySearchTree::Search(T target, TreeNode *node)
{
	if (node == 0 || node->data == target)
		return node;

	if (target < node->data)
		return Search(target, node->left);
	else
		return Search(target, node->right);
}

template 
TreeNode* BinarySearchTree::Minimum(TreeNode *node)
{
	while (node!=0 && node->left!=0)
	{
		node = node->left;
	}

	return node;
}

template 
TreeNode* BinarySearchTree::Maximum(TreeNode *node)
{
	while (node!=0 && node->right!=0)
	{
		node = node->right;
	}

	return node;
}

template 
TreeNode* BinarySearchTree::Successor(TreeNode *node)
{
	if (node->right != 0)
		return Minimum(node->right);

	while (node->parent!=0 && node == node->parent->right)	// parent.data < node.data
	{
		node = node->parent;
	}

	return node->parent;
}

template 
TreeNode* BinarySearchTree::Predecessor(TreeNode *node)
{
	if (node->left != 0)
		return Maximum(node->left);

	while (node->parent!=0 && node==node->parent->left) // parent.data > node.data
	{
		node = node->parent;
	}

	return node->parent;
}


template 
void BinarySearchTree::Insert(TreeNode *node)
{
	TreeNode *parentNode = 0;
	TreeNode *currentNode = root;

	while (currentNode != 0)	// 确定node的父节点(即插入位置)
	{
		parentNode = currentNode;
		if (node->data < currentNode->data)
			currentNode = currentNode->left;
		else
			currentNode = currentNode->right;
	}

	node->parent = parentNode;

	if (parentNode == 0)	// 空树
		root = node;
	else
	{
		if (node->data < parentNode->data)	// 确定node为父节点的左子结点还是右子节点
			parentNode->left = node;
		else
			parentNode->right = node;
	}
}

template 
TreeNode* BinarySearchTree::Delete(TreeNode *node)
{
	// 确定需要删除的节点的位置
	TreeNode* delNode;
	if (node->left==0 || node->right==0)
		delNode = node;
	else
		delNode = Successor(node);


	// 
	TreeNode* nonNullChildNode;
	if (delNode->left != 0)
		nonNullChildNode = delNode->left;
	else
		nonNullChildNode = delNode->right;

	if (nonNullChildNode != 0)
		nonNullChildNode->parent = delNode->parent;

	if (delNode->parent == 0)
		root = nonNullChildNode;
	else if (delNode == delNode->parent->left)
		delNode->parent->left = nonNullChildNode;
	else
		delNode->parent->right = nonNullChildNode;

	if (delNode != node)
		node->data = delNode->data;

	return delNode;

}


测试程序:

// main.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include "BinarySearchTree.h"

int _tmain(int argc, _TCHAR* argv[])
{
	int data[] = {15, 6, 18, 3, 7, 17, 20, 2, 4, 13, 9};

// 	BinarySearchTree bst;
// 	for (int i=0; i<sizeof(data)/sizeof(int); ++i)
// 	{
// 		bst.Insert(data[i]);
// 	}

	BinarySearchTree bst(data, sizeof(data)/sizeof(int));
	
	cout << sizeof(data) << endl;
	bst.InOrderTreeWalk();
	bst.MaxValue();
	bst.MinValue();
	bst.Delete(6);
	bst.InOrderTreeWalk();
	bst.Successor(20);
	bst.Predecessor(2);
	bst.Predecessor(13);

	return 0;
}


随机构造的二叉查找树:

使用随机方法由输入序列构造二叉查找树,它通过按随机的顺序,将序列中各元素插入一颗初始为空的树。输入元素的各种排列是等概率的。

随机构造的二叉查找树的期望高度为:$$O(\lg{n})$$。

对上述程序中的部分代码进行修改即可使用随机方法构造二叉查找树,修改、添加的代码如下:

#include 
#include 

template 
class BinarySearchTree
{
public:
	BinarySearchTree(T* dataArray, int count);	// 使用数组构造二叉查找树(随机构造版本)

private:
	void RandomizedInsert(T* dataArray, int start, int end);	// 随机插入算法
};

template 
BinarySearchTree::BinarySearchTree(T* dataArray, int count)
{
	root = 0;
	srand(time(0));	// 初始化随机数
	RandomizedInsert(dataArray, 0, count-1);
		
}

template 
void BinarySearchTree::RandomizedInsert(T* dataArray, int start, int end)
{
	if (start > end)
		return;

	if (start == end)
	{
		Insert(dataArray[start]);
		return;
	}

	int randPos = start + (double)rand() / RAND_MAX * (end-start);	// 随机选择插入元素
	Insert(dataArray[randPos]);
	RandomizedInsert(dataArray, start, randPos-1);
	RandomizedInsert(dataArray, randPos+1, end);
}

使用模板类为什么出现“unresolved external symbol”?

在使用模板类时,如果将模板类的声明和实现分别放在.H和.CPP文件中的话,在使用该模板类时会遇到连接错误:“Wunresolved external symbol”。

原因如下:模板类、模板函数直到其被使用时才会实例化,当一个模板类被使用时,编译器需要其成员函数的完整代码才可以建立指定类型的函数版本。然而,当函数实现在额外的.CPP文件中时,编译器无法获得函数的完整代码,无法实例化指定类型的函数。

解决方法:

1) 将模板类的声明和实现全部放在.h文件中(建议采用此方式)

2) 将所有模板类的成员函数声明为内嵌函数(inline)

3) 在模板类的成员函数前添加export(部分编译器不支持)

参考资料:stackoverflow

派生类的构造与析构


(1) 函数执行顺序

派生类构造时:首先调用基类的构造函数,然后调用派生类自身的构造函数。

派生类析构时:首先调用派生类自身的析构函数,然后调用各基类的构造函数。

#include 

class A
{
public:
	A(void)
	{
		cout << "base: A constructor" << endl;
	};

	~A(void)
	{
		cout << "base: A destructor" << endl;
	};
};

class B : public A
{
public:
	B(void)
	{
		cout << "B constructor" << endl;
	};

	~B(void)
	{
		cout << "B destructor" << endl;
	};
};

int main(int argc, char* argv[])
{
	//A a;
	B b;
	return 0;
}

程序输出:

base: A constructor
derived: B constructor
derived: B destructor
base: A destructor


(2) 构造函数参数传递