在当今的大多数nVIDIA GPU上,共享内存的大小(OpenCL术语中的"本地内存")仅为16 KiB.
我有一个应用程序,我需要创建一个具有10,000个整数的数组.所以我需要适应10,000个整数的内存量= 10,000*4b = 40kb.
我试图了解手写内核的每个CUDA线程的资源使用情况.
我把我的kernel.cu文件编译成了一个kernel.o文件nvcc -arch=sm_20 -ptxas-options=-v
我得到了以下输出
ptxas info : Compiling entry function 'searchkernel(octree, int*, double, int, double*, double*, double*)' for 'sm_20'
ptxas info : Function properties for searchkernel(octree, int*, double, int, double*, double*, double*)
72 bytes stack frame, 0 bytes spill stores, 0 bytes spill loads
ptxas info : Used 46 registers, 176 bytes cmem[0], 16 bytes cmem[14]
Run Code Online (Sandbox Code Playgroud)
看看上面的输出,这是正确的
我在理解输出方面也遇到了一些问题.
我的内核调用了很多c++filt函数.IS 72字节是__device__和__global__函数堆栈帧的内存总和?
__device__和之间有什么区别0 byte spill stores …
假设我有一堆向量:
vector<int> v1;
vector<double> v2;
vector<int> v3;
Run Code Online (Sandbox Code Playgroud)
所有相同的长度.现在,对于每个索引i,我希望能够将(v1 [i],v2 [i],v3 [i])视为元组,并且可以传递它.事实上,我希望有一个元组向量而不是向量元组,我可以使用它来完成上述操作.(用C语言,我可能会说结构数组而不是数组结构).我不想影响任何数据重新排序(想想:真正长的向量),即新的向量由我传入的各个向量支持.让我们.
现在,我希望我编写的类(ToVBackedVoT因缺少一个更好的名称而调用它)来支持任意选择向量来支持它(不仅仅是3,不是int,double和int,不是每个只是标量).我希望元组的向量是可变的,并且不需要在构造/赋值上进行复制.
如果我理解正确,可变参数模板和std::tupleC++ 11中的新类型是这样做的手段(假设我不想要无类型void*数组等).但是,我几乎不了解它们,也从未与它们合作过.你能帮我勾勒出这样一堂课的样子吗?或者如何,给定
template <typename ... Ts>
Run Code Online (Sandbox Code Playgroud)
我可以表达一些类似"模板参数列表是用这种类型的元素向量替换原始模板参数中的每个类型名称"吗?
注意:我想我可能也想稍后能够将其他向量连接到支持向量,从而创建一个实例ToVBackedVoT<int, double, int>,例如,一个实例ToVBackedVoT<int, double, int, unsigned int>.所以,在回答时请记住这一点.但这并不是至关重要的.
在使用C++一段时间后,我回到了一些C开发阶段.我已经明白,如果没有必要支持让编译器在编译时为你做更多工作,应该避免使用宏.因此,对于常量值,在C++中我会使用静态const变量,或者使用C++ 11枚举类来实现更好的范围.在C中,静态常量不是真正的编译时常量,枚举可能(?或可能不?)的行为略有不同.
那么,更喜欢使用枚举作为常量而不是#defines是否合理?
作为参考,这里有一个很好的列表,包括枚举,#define和C++中的静态consts.
CUDA Runtime API公开了这些功能
cudaRuntimeGetVersion() 和cudaDriverGetVersion() (见这里的详细说明).我有点期待第一个给我"8.0"(对于CUDA 8.0),第二个给我一个字符串,就像我从检查nVIDIA的GPU驱动程序内核模块得到的那样,例如
modinfo nvidia | grep "^version:" | sed 's/^version: *//;'
Run Code Online (Sandbox Code Playgroud)
在我的系统上367.57.
现在,第一个电话给了我8000- 很好,只是一个奇怪的方式说8.0我猜; 但第二个API调用也给了我8000.那么这两个意味着什么?
我链接到的Runtime API文档似乎没有解释这一点.
Consider the following code:
template <typename T> int foo();
template <typename T> int foo() = delete;
Run Code Online (Sandbox Code Playgroud)
is this valid C++11?
... see it all on GodBolt.
so which compilers are right and which compilers are s@#$%e ? :-)
为什么MapJava中的接口没有removeAll(Collection<?> c)像删除密钥的方法map.remove(Object)?
我知道我可以随时做map.keySet().removeAll(..)..但这是一个Map没有的原因removeAll()并鼓励我们一起去map.keySet().removeAll(..)吗?
一篇C++ Next博客文章说
A compute(…)
{
A v;
…
return v;
}
Run Code Online (Sandbox Code Playgroud)
如果A具有可访问的副本或移动构造函数,则编译器可以选择忽略该副本.否则,如果A有移动构造函数,v则移动.否则,如果A有复制构造函数,v则复制.否则,将发出编译时错误.
我以为我应该总是返回值,std::move
因为编译器能够找出用户的最佳选择.但另一个例子来自博客文章
Matrix operator+(Matrix&& temp, Matrix&& y)
{ temp += y; return std::move(temp); }
Run Code Online (Sandbox Code Playgroud)
这std::move是必要的,因为y必须将其视为函数内的左值.
啊,在研究这篇博文之后,我的脑袋几乎爆炸了.我尽力去理解推理,但是我学的越多,我就越困惑.我们为什么要借助于这个价值来回报这个价值std::move?
毫无疑问,很多人都熟悉Alexandrescus ScopeGuard先生模板(现在是Loki的一部分)和新版ScopeGuard11:http://channel9.msdn.com/Shows/Going+Deep/C-and-Beyond-2012- 安德烈- Alexandrescu的系统性,错误处理-在-C
来源:https: //gist.github.com/KindDragon/4650442
在他在c ++和2012年以后的演讲中,他提到他无法找到一种方法来正确检测范围是否因异常而退出.因此,当且仅当由于异常而退出作用域时,他才能实现SCOPE_FAIL宏,该宏将执行提供的lambda(通常用于回滚代码).这将使得dismiss()成员函数不再需要,并使代码更具可读性.
既然我不像Alexandrescu先生那样天才或经验丰富,我希望实施SCOPE_FAIL并不像以下那么容易:
~ScopeGuard11(){ //destructor
if(std::uncaught_exception()){ //if we are exiting because of an exception
f_(); //execute the functor
}
//otherwise do nothing
}
Run Code Online (Sandbox Code Playgroud)
我的问题是为什么不呢?
我刚读完
坦率地说,我只能挠头。
让我们从@NicolBolas 接受的答案中的第二个例子开始:
Run Code Online (Sandbox Code Playgroud)aligned_storage<sizeof(int), alignof(int)>::type data; new(&data) int; int *p = std::launder(reinterpret_cast<int*>(&data));[basic.life]/8 告诉我们,如果在旧对象的存储中分配新对象,则无法通过指向旧对象的指针访问新对象。
std::launder允许我们回避这一点。
那么,为什么不改变语言标准,以便data通过 a访问reinterpret_cast<int*>(&data)是有效/适当的?在现实生活中,洗钱是一种向法律隐瞒现实的方式。但我们没有什么可隐瞒的——我们在这里做的事情完全合法。那么当编译器std::launder()注意到我们正在以data这种方式访问时,为什么不能将其行为更改为它的行为呢?
继续第一个例子:
Run Code Online (Sandbox Code Playgroud)X *p = new (&u.x) X {2};因为 X 是微不足道的,我们不需要在创建一个新对象之前销毁旧对象,所以这是完全合法的代码。新对象的 n 成员将为 2。
所以告诉我……什么会
u.x.n回来?显而易见的答案是 2。但这是错误的,因为允许编译器假设一个真正的
const变量(不仅仅是一个 const&,而是一个声明的对象变量const)永远不会改变。但我们只是改变了它。
那么,为什么不使编译器不能被允许作一个假设,当我们写这样的代码,通过该指针访问恒场?
为什么使用这个伪函数来在形式语言语义中打一个洞是合理的,而不是根据代码是否像这些示例中那样将语义设置为它们需要的样子?