Parallel processing 理解CUDA索引
我继承了一些需要处理的CUDA代码,但其中的一些索引工作让我感到困惑 一个简单的例子是数据的标准化。假设我们有一个共享数组Parallel processing 理解CUDA索引,parallel-processing,cuda,Parallel Processing,Cuda,我继承了一些需要处理的CUDA代码,但其中的一些索引工作让我感到困惑 一个简单的例子是数据的标准化。假设我们有一个共享数组a[2*N],它是一个2xN形状的矩阵,已经展开为一个数组。然后我们有归一化平均值和标准偏差:norm\u表示[2]和norm\u-stds[2]。目标是以并行的方式对数据进行标准化。一个最简单的例子是: __global__ void normalise(float *data, float *norm, float *std) { int tdy = threadIdx.
a[2*N]
,它是一个2xN形状的矩阵,已经展开为一个数组。然后我们有归一化平均值和标准偏差:norm\u表示[2]
和norm\u-stds[2]
。目标是以并行的方式对数据进行标准化。一个最简单的例子是:
__global__ void normalise(float *data, float *norm, float *std) {
int tdy = threadIdx.y;
for (int i=tdy; i<D; i+=blockDim.y)
data[i] = data[i] * norm[i] + std[i];
}
int main(int argc, char **argv) {
// generate data
int N=100;
int D=2;
MatrixXd A = MatrixXd::Random(N*D,1);
MatrixXd norm_means = MatrixXd::Random(D,1);
MatrixXd norm_stds = MatrixXd::Random(D,1);
// transfer data to device
float* A_d;
float* norm_means_d;
float* nrom_stds_d;
cudaMalloc((void **)&A_d, N * D * sizeof(float));
cudaMalloc((void **)&norm_means_d, D * sizeof(float));
cudaMalloc((void **)&norm_stds_d, D * sizeof(float));
cudaMemcpy(A_d, A.data(), D * N * sizeof(float), cudaMemcpyHostToDevice);
cudaMemcpy(norm_means_d, norm_means.data(), D * sizeof(float), cudaMemcpyHostToDevice);
cudaMemcpy(norm_stds_d, norm_stds.data(), D * sizeof(float), cudaMemcpyHostToDevice);
// Setup execution
const int BLOCKSIZE_X = 8;
const int BLOCKSIZE_Y = 16;
const int GRIDSIZE_X = (N-1)/BLOCKSIZE_X + 1;
dim3 dimBlock(BLOCKSIZE_X, BLOCKSIZE_Y, 1);
dim3 dimGrid(GRIDSIZE_X, 1, 1);
normalise<<dimGrid, dimBlock, 0>>>(A_d, norm_means_d, norm_stds_d);
}
程序停止工作,只输出乱七八糟的数据
有人能解释我为什么会有这种行为吗
PS.我对CUDA非常陌生拥有一个二维内核来对数组执行元素操作确实是毫无意义的。也没有理由在8x16大小的块中工作。但是修改后的内核只使用第二维度(y);这可能就是它不起作用的原因。您可能只需要使用第一个维度(x) 但是,将Y尺寸用于实际的第二个尺寸是合理的,例如:
__global__ void normalize(
float __restrict *data,
const float __restrict *norm,
const float __restrict *std)
{
auto pos = threadIdx.x + blockDim.x * blockIdx.x;
auto d = threadIdx.y + blockDim.y * blockIdx.y; // or maybe just threadIdx.y;
data[pos + d * N] = data[pos + d * N] * norm[d] + std[d];
}
其他需要考虑的问题:
- 我在指针中添加了
。相关的时候一定要这样做李>\u restrict
- 让一个线程处理多个数据元素是一个好主意,但您应该在更长的维度中实现这一点,线程可以重用其norm和std值,而不是每次都从内存中读取它们
- 使用二维内核对数组执行元素操作确实毫无意义。也没有理由在8x16大小的块中工作。但是修改后的内核只使用第二维度(y);这可能就是它不起作用的原因。您可能只需要使用第一个维度(x)
但是,将Y尺寸用于实际的第二个尺寸是合理的,例如:
__global__ void normalize(
float __restrict *data,
const float __restrict *norm,
const float __restrict *std)
{
auto pos = threadIdx.x + blockDim.x * blockIdx.x;
auto d = threadIdx.y + blockDim.y * blockIdx.y; // or maybe just threadIdx.y;
data[pos + d * N] = data[pos + d * N] * norm[d] + std[d];
}
其他需要考虑的问题:
- 我在指针中添加了
。相关的时候一定要这样做李>\u restrict
- 让一个线程处理多个数据元素是一个好主意,但您应该在更长的维度中实现这一点,线程可以重用其norm和std值,而不是每次都从内存中读取它们