我有一个关于 CUDA C++ 编程的问题。我正在使用共享内存。但我需要更大的共享内存。所以我试图重用共享内存。我的代码是这样的:
__global__ void dist_calculation(...){
..........
{
//1st pass
__shared__ short unsigned int shared_nodes[(number_of_nodes-1)*blocksize];
............
}
{
//2nd pass
__shared__ float s_distance_matrix[(number_of_nodes*(number_of_nodes-1))/2];
........
}
}
Run Code Online (Sandbox Code Playgroud)
共享内存不能同时容纳shared_nodes
和s_distance_matrix
。但它可以单独容纳每个(我已经测试过)。在第二遍中,程序无法识别 shared_nodes
(因为它来自第一遍),但向我显示共享内存没有足够空间的错误。所以看起来,仍然为shared_nodes
变量分配了一些空间。有什么方法可以销毁该分配(例如cudaFree
)?或任何其他建议?
根据我在CUDA文档中的描述,共享内存库冲突与sm_20及更高版本无关,因为在同时请求时会广播值,从而防止出现任何类型的序列化延迟.
文件:
共享存储器硬件在计算能力2.x的设备上得到改进,以支持多个广播字,并且为每个线程的8位,16位,64位或128位的访问产生更少的存储体冲突(G部分). 4.3).
有人可以证实我的断言吗?
我想在我的OpenCL内核中优化我的本地内存访问模式.我在某处读到了可配置的本地内存.例如,我们应该能够配置哪个量用于本地mem以及哪个量用于自动缓存.
另外我读到银行大小可以在这里选择最新的(开普勒)Nvidia硬件:http: //www.acceleware.com/blog/maximizing-shared-memory-bandwidth-nvidia-kepler-gpus.这一点对于本地存储器中的双精度值存储似乎非常关键.
Nvidia是否提供专门为CUDA用户设置本地内存的功能?我找不到OpenCL的类似方法.这可能是以不同的方式调用,还是真的不存在?
我有两个 CUDA 内核可以计算类似的东西。一种是使用全局内存(myfun
是一种从全局内存读取大量数据并进行计算的设备函数)。第二个内核将该数据块从全局内存传输到共享内存,以便数据可以在块的不同线程之间共享。我使用全局内存的内核比使用共享内存的内核快得多。可能的原因有哪些?
loadArray
仅复制d_x
to的一小部分m
。
__global__ void mykernel(float *d_x, float *d_y, int *d_z, float *d_u, int N, int K, int D)
{
int tid = blockIdx.x*blockDim.x + threadIdx.x;
int index = 0;
float max_s = 1e+37F;
if (tid < N)
{
for (int i = 0; i < K; i++)
{
float s = myfun(&d_x[i*D], d_y, tid);
if (s > max_s)
{
max_s = s;
index = i;
}
}
d_z[tid] = index;
d_u[tid] …
Run Code Online (Sandbox Code Playgroud) 我读了一些引用本地内存的CUDA文档.(这主要是早期文档.)设备属性报告本地mem大小(每个线程)."本地"记忆是什么意思?什么是'本地'记忆?"本地"记忆在哪里?如何访问"本地"内存?这是__device__
记忆,不是吗?
设备属性还报告:全局,共享和常量mem大小.这些陈述是否正确:
全局记忆是__device__
记忆.它具有网格范围和网格(内核)的生命周期.
常量内存是__device__ __constant__
内存.它具有网格范围和网格(内核)的生命周期.
共享内存是__device__ __shared__
内存.它具有单个块范围和该块(线程)的生命周期.
我在想共享内存是SM内存.即只有那个SM才能直接访问的内存.资源相当有限.SM是不是一次分配了一堆块?这是否意味着SM可以交错执行不同的块(或不是)?即运行阻止*A*线程直到它们停止.然后运行block*B*线程直到它们停止.然后再次换回阻止*A*线程.或者SM是否为块*A*运行一组线程,直到它们停止.然后交换另一组块*A*线程.此交换继续,直到块*A*用尽.然后,只有这样才能在块*B*上开始工作.因为共享记忆,我问.如果单个SM从2个不同的块交换代码,那么SM如何快速交换/分出共享内存块?(我认为后来的senerio是真的,并且没有交换共享内存空间.块*A*运行直到完成,然后块*B*开始执行.注意:块*A*可能是不同的内核比块*B*.)
我正在尝试编译一个包含 MSVS 2012 和 CUDA 内核的程序。我使用共享内存,但与此问题中关于同一问题的问题不同,我只对该内核的共享内存使用我的变量名称一次,因此不存在重新定义的问题。使用这样的代码:
template<typename T>
__global__ void mykernel(
const T* __restrict__ data,
T* __restrict__ results)
{
extern __shared__ T warp_partial_results[];
/* ... */
warp_partial_results[lane_id] = something;
/* ... */
results[something_else] = warp_partial_results[something_else];
/* ... */
}
Run Code Online (Sandbox Code Playgroud)
它被实例化为多种类型(例如 float、int、unsigned int),我得到了可怕的
Run Code Online (Sandbox Code Playgroud)declaration is incompatible with previous "warp_partial_results"
信息。什么可能导致这种情况?
我是 CUDA 新手,正在从事个人项目。我知道,如果您想在启动时指定共享内存量:
kernel<<<grid_size,block_size,shared_mem_size>>>(parameters);
Run Code Online (Sandbox Code Playgroud)
另一方面,如果我想将内核放入流中:
kernel<<<grid_size,block_size,0,stream_being_used>>>(parameters);
Run Code Online (Sandbox Code Playgroud)
我不明白为什么第三个参数在流的情况下是0?(我是从 Sanders 和 Kandrot 的《CUDA 示例》第 10 章中得到的)。
如果我想在启动时指定共享内存并将其放入流中,我该如何正确执行此操作?换句话说,中间的参数应该<<<...>>>
是什么样的?
我想写下面的CUDA函数:
void foo(int* a, size_t n)
{
if ( /* MAGIC 1 */ ) {
// a is known to be in shared memory,
// so use it directly
}
else {
// make a copy of a in shared memory
// and use the copy
}
}
Run Code Online (Sandbox Code Playgroud)
在主机端,我们有一个与cudaPointerGetAttributes形式有关的设施,可以告诉我们指针是指设备内存还是主机内存; 也许有一些方法可以区分设备代码中的指针,也许它也可以从全局指针中辨别共享.或者,也许甚至更好 - 也许有一个编译时机制来做到这一点,因为毕竟设备功能只被编译到内核中并且不是独立的,所以nvcc
通常可以知道它们是否与共享内存一起使用.
我无法找到在 CUDA C 中使用共享内存转置非平方矩阵的方法。(我是 CUDA C 和 C 的新手)
在这篇博客文章中,展示了如何转置矩阵的有效方法(通过共享内存合并转置)。但它只适用于方阵。
github上也提供了代码(与博客上相同)。
StackOverflow 上也有类似的问题。有TILE_DIM = 16
设定。但通过该实现,每个线程只需将矩阵的一个元素复制到结果矩阵。
这是我当前的实现:
__global__ void transpose(double* matIn, double* matTran, int n, int m){
__shared__ double tile[TILE_DIM][TILE_DIM];
int i_n = blockIdx.x*TILE_DIM + threadIdx.x;
int i_m = blockIdx.y*TILE_DIM + threadIdx.y; // <- threadIdx.y only between 0 and 7
// Load matrix into tile
// Every Thread loads in this case 4 elements into tile.
int i;
for (i = 0; i < …
Run Code Online (Sandbox Code Playgroud) 我想确保我正确理解共享内存中的库冲突。
我有32段数据。
这些段分别由 128 个整数组成。
[[0, 1, ..., 126, 127], [128, 129, ..., 255], ..., [3968, 3969, ..., 4095]]
Run Code Online (Sandbox Code Playgroud)
warp 中的每个线程仅访问其自己的部分。
线程 0 访问对应于索引 0 的部分 0 的位置 0。
线程 1 访问部分 1 上对应于索引 128 的位置 0。
...
线程 31 访问对应于索引 3968 的部分 31 的位置 0。
这是否意味着我有32倍的银行冲突?
如果是,那么如果我向每个段添加一个填充元素(即总共 129 个元素),那么每个线程将访问一个唯一的存储体。我对吗?