两个问题:
根据 Nsight Compute 的说法,我的内核是受计算限制的。相对于峰值性能的 SM 利用率为 74%,内存利用率为 47%。然而,当我查看每个管道利用率时,LSU 利用率远高于其他管道(75% 与 10-15%)。这难道不表明我的内核受内存限制吗?如果计算和内存资源的利用率与管道利用率不对应,我不知道如何解释这些术语。
调度程序每 4 个周期才发出一次,这是否意味着我的内核受到延迟限制?人们通常根据计算和内存资源的利用率来定义它。两者之间是什么关系?
假设我有一个myapp不需要命令行参数的可执行文件,并启动 CUDA 内核mykernel。我可以调用:
nv-nsight-cu-cli -k mykernel myapp
Run Code Online (Sandbox Code Playgroud)
并得到如下所示的输出:
==PROF== Connected to process 30446 (/path/to/myapp)
==PROF== Profiling "mykernel": 0%....50%....100% - 13 passes
==PROF== Disconnected from process 1234
[1234] myapp@127.0.0.1
mykernel(), 2020-Oct-25 01:23:45, Context 1, Stream 7
Section: GPU Speed Of Light
--------------------------------------------------------------------
Memory Frequency cycle/nsecond 1.62
SOL FB % 1.58
Elapsed Cycles cycle 4,421,067
SM Frequency cycle/nsecond 1.43
Memory [%] % 61.76
Duration msecond 3.07
SOL L2 % 0.79
SM Active Cycles cycle 4,390,420.69
(etc. etc.)
-------------------------------------------------------------------- …Run Code Online (Sandbox Code Playgroud) 我需要形成各种命令的管道。管道的某些元素或元素序列仅在某些条件成立时才相关。现在,我可以写:
if [[ $whatever ]]; then
cmd1 | cmd2 | cmd3 | cmd4
else
cmd1 | cmd4
fi
Run Code Online (Sandbox Code Playgroud)
但这意味着重复cmd1and cmd4,另外,可能有几个条件,我不想写嵌套的 if 。所以,我试着写这个:
if [[ $whatever ]]; then
pipeline_segment="| cmd2 | cmd3"
else
pipeline_segment=""
fi
cmd1 ${pipeline_segment} | cmd4
Run Code Online (Sandbox Code Playgroud)
但是 - 管道符号没有被解释为使用管道的指令。
我如何让 bash 也执行我想要的管道?
注意:您可以假设 bash 版本为 4 或更高,但前提是您必须这样做。
根据变量的类型,我想调用模板化函数(给出)。问题是,模板的预期类型不会直接适合。
示例:如果我的变量的类型是int,那么我想调用该函数foo<classA>()。如果类型是double我想打电话
foo<classB>()等等......
到目前为止,我已经在 switch case 中调用了该函数。
我的问题是:有没有办法“翻译”类型?…… 就像我传递的函数一样int,我会classA回来?这样我就可以简单地调用这个函数:foo<translate_type(variable)> foo()
正如我所写的,我尝试过的是一个开关盒。另一种可能性可能是围绕模板的模板化函数。一个接受 egint然后调用正确的函数foo<classA>()。此外,我想避免使用宏。
也许现代 C++ 有更好的方法?一种在不使用案例的情况下可维护性更好的方法。
我想知道为什么它们具有相同的内存地址,如果我没记错的话,每个线程都有一个自己的已创建变量的副本,这样:
__global__ void
Matrix_Multiplication_Shared(
const int* const Matrix_A,
const int* const Matrix_B,
int* const Matrix_C)
{
const int sum_value = threadIdx.x;
printf("%p \n", &sum_value);
}
Run Code Online (Sandbox Code Playgroud)
输出:
我正在考虑一个线程块的情况,例如有 2 个或更多线程。
如果我们写如下函数:
auto foo() {
Foo foo { /* ... */ };
do_stuff(foo);
return foo;
}
Run Code Online (Sandbox Code Playgroud)
然后NRVO应该启动,这样foo就不会在返回时被复制。
现在假设我想返回两个不同的值:
auto foo() {
Foo foo { /* ... */ };
Bar bar { /* ... */ };
do_stuff(foo, bar);
return std::make_tuple(foo, bar);
}
Run Code Online (Sandbox Code Playgroud)
这种幼稚的实现可能会触发构建每个Foo和Bar( GodBolt)的两个副本。
我应该如何最好地修改我的代码以避免这种复制,而不会弄乱我的返回类型?
据我所知,你需要一个主机代码(对于CPU)和一个设备代码(对于GPU),没有它们你就无法在GPU上运行某些东西。
我正在学习 PTX ISA,但不知道如何在 Windows 上执行它。我是否需要 .cu 文件来运行它,或者是否有其他方法来运行它?
在 C(和其他语言)中,对变量和函数的名称使用前缀和后缀是很常见的。_x特别是,人们偶尔会在“正确的”标识符(例如_y变量等)之前或之后看到下划线的使用。_print但是,还有一种常识是避免以下划线开头的名称,以免与 C 标准发生冲突库实施。
那么,什么地方、什么地方可以使用下划线呢?
考虑以下 CUDA 函数:
__device__ int foo_f() { return ceilf(1007.1111); }
Run Code Online (Sandbox Code Playgroud)
应该很容易对其进行优化以生成仅返回 1008 的设备函数:
mov.u32 %r1, 1008;
st.param.b32 [func_retval0+0], %r1;
ret;
Run Code Online (Sandbox Code Playgroud)
但相反,它编译(使用 NVCC 11.5)成本更高:
mov.f32 %f1, 0f447C0000;
cvt.rzi.s32.f32 %r1, %f1;
st.param.b32 [func_retval0+0], %r1;
ret;
Run Code Online (Sandbox Code Playgroud)
如果代码是:
static __device__ int poor_mans_ceilf(float x)
{
return (int) x + ( ((float)(int) x < x) ? 1 : 0);
}
__device__ int foo_pf() { return poor_mans_ceilf(1007.1111); }
Run Code Online (Sandbox Code Playgroud)
编译器应该更容易“注意到”这是一个优化机会。
那么,为什么 NVCC 未能在这里进行优化(而典型的 C/C++ 编译器确实会进行优化)?是否存在一些微妙的问题阻止(编辑)PTX 代码的优化?我意识到ptxas最终有机会优化它,但这不是特定于微架构的优化。
在 上查看这一切GodBolt …
我有这样的代码:
std::string getInfo(FILE *fp)
{
char buffer[30];
if (fread(buffer, 19, 1, fp) == 1)
buffer[19] = '\0';
else
buffer[0] = '\0';
return buffer;
}
Run Code Online (Sandbox Code Playgroud)
我正在使用 cppcheck 进行静态分析,它会发出警告:
error: Resource leak: fp [resourceLeak]
return buffer;
^
Run Code Online (Sandbox Code Playgroud)
在我看来,由于返回是按值计算的,因此数据将从“缓冲区”复制到 std::string 的存储中,因此不会发生泄漏。
这会带来一些真正的问题还是误报?