CUDA 中的原子操作失败

2024-06-21

由于计算能力为2.1,atomicAdd and atomicMax操作不支持双精度,那么我根据堆栈溢出的一些答案定义这两个函数。

奇怪的是atomicAdd功能运行良好,但atomicMax不起作用,这是我的代码。

我的代码的测试是在每个块上生成随机数,然后将每个块上的随机数相加,我们有块总和,我想测试atomicAdd and atomicMax关于区块总和。

#include <iostream>
#include <curand.h>
#include <curand_kernel.h>
#include <stdio.h>
#include <stdlib.h>


#define num_of_blocks 2
#define threads_per_block 2
#define tot_threads 4


__device__ double gsum[num_of_blocks];

__device__ double dev_sum;

__device__ double dev_max;

// set seed for random number generator
__global__ void initcuRand(curandState* globalState, unsigned long seed){
    int idx = threadIdx.x + blockIdx.x * blockDim.x;
    curand_init(seed, idx, 0, &globalState[idx]);
}

// atomiMax for double
__device__ double atomicMax_d(double* address, double val)
{
    unsigned long long int* address_as_i = (unsigned long long int*)address;
    unsigned long long int old = *address_as_i, assumed;
    do {
        assumed = old;
        old = ::atomicCAS(address_as_i, assumed, __double_as_longlong(::fmax(val, __longlong_as_double(assumed))));
    } while (assumed != old);
    return __longlong_as_double(old);
}

// atomicAdd for double
__device__ double atomicAdd_d(double* address, double val)
{
    unsigned long long int* address_as_ull = (unsigned long long int*)address;
    unsigned long long int old = *address_as_ull, assumed;
    do{
        assumed = old;
        old = atomicCAS(address_as_ull, assumed, __double_as_longlong(val + __longlong_as_double(assumed)));
    }while(assumed != old);
    return __longlong_as_double(old);
}

__global__ void kernel(curandState *globalState){
    // global id
    int gidx    = threadIdx.x + blockIdx.x * blockDim.x;
    // local id
    int lidx    = threadIdx.x;

    // creat shared memory to store seeds
    __shared__ curandState localState[tot_threads];

    __shared__ double srandnum[threads_per_block];

    // copy global seed to local
    localState[lidx]    = globalState[gidx];

    //synchronize the local threads writing to the local memory cache
    __syncthreads();

    // generate random number from normal distribution in shared memory
    srandnum[lidx]  = curand_normal(&localState[lidx]);
    __syncthreads();

    if(lidx == 0){srandnum[lidx] += srandnum[lidx + 1];}   // sum of each block
    if(lidx == 0){gsum[blockIdx.x] = srandnum[lidx];}      // copy the sums back to global memory

    __threadfence();

    if( gidx < num_of_blocks){
        atomicAdd_d(&dev_sum, gsum[gidx]);
    }

    if( gidx < num_of_blocks){
        atomicMax_d(&dev_max, gsum[gidx]);
    }

    if( gidx == 0){
        printf("Sum is: %lf\n", dev_sum);
    }

    if( gidx == 1){
        printf("Max is: %lf\n", dev_max);
    }
}


int main(){
    // set seed on device
    curandState *globalState;
    cudaMalloc((void**)&globalState, tot_threads*sizeof(curandState));
    initcuRand<<<num_of_blocks, threads_per_block>>>(globalState, 1);

    // launch kernel
    kernel<<<num_of_blocks, threads_per_block>>>(globalState);
    double randnum[num_of_blocks];

    cudaMemcpyFromSymbol(randnum, gsum, num_of_blocks*sizeof(double), 0, cudaMemcpyDeviceToHost);

    std::cout << "Sum of each block:\n";
    for (int i = 0; i < num_of_blocks; ++i){
        std::cout << randnum[i] << std::endl;
    }

    cudaFree(globalState);
    return 0;
}

我得到的结果是

Sum is: -0.898329
Max is: 0.000000
Sum of each block:
-0.0152994
-0.88303

从结果来看,我知道atomicAdd功能有效,但atomicMax功能不起作用,我对此一无所知。预先感谢。


你永远不会初始化dev_max or dev_sum。如果它们不以已知值开头,则您无法明智地对它们执行这些类型的原子操作。

尝试这样的事情:

__device__ double dev_sum = 0.0;

__device__ double dev_max = -1e99;

我想你会对结果感到更满意。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

CUDA 中的原子操作失败 的相关文章

  • __device__ __constant__ 常量

    有什么区别吗 在 CUDA 程序中定义设备常量的最佳方法是什么 在 C 主机 设备程序中 如果我想将常量定义在设备常量内存中 我可以这样做 device constant float a 5 constant float a 5 问题 1
  • 如何使用 CUDA/Thrust 对两个数组/向量根据其中一个数组中的值进行排序

    这是一个关于编程的概念问题 总而言之 我有两个数组 向量 我需要对一个数组 向量进行排序 并将更改传播到另一个数组 向量中 这样 如果我对 arrayOne 进行排序 则对于排序中的每个交换 arrayTwo 也会发生同样的情况 现在 我知
  • VS 程序在调试模式下崩溃,但在发布模式下不崩溃?

    我正在 VS 2012 中运行以下程序来尝试 Thrust 函数查找 include cuda runtime h include device launch parameters h include
  • 将 nvidia 运行时添加到 docker 运行时

    我正在运行虚拟机GCP配备特斯拉 GPU 并尝试部署一个PyTorch基于应用程序使用 GPU 加速 我想让 docker 使用这个 GPU 可以从容器访问它 我设法在主机上安装了所有驱动程序 并且该应用程序在那里运行良好 但是当我尝试在
  • OS X 10.8 上的 PyCuda / 多处理问题

    我正在开发一个项目 将计算任务分配给多个 python 进程 每个进程都与其自己的 CUDA 设备关联 生成子进程时 我使用以下代码 import pycuda driver as cuda class ComputeServer obje
  • cuda-gdb 错误消息

    我尝试使用 cuda gdb 调试我的 CUDA 应用程序 但遇到了一些奇怪的错误 我设置了选项 g G O0构建我的应用程序 我可以在没有 cuda gdb 的情况下运行我的程序 但没有得到正确的结果 因此我决定使用 cuda gdb 但
  • 大型跨平台软件项目的技巧/资源

    我将开始一个大型软件项目 涉及跨平台 GUI 和大量的数字运算 我计划用 C 和 CUDA 编写大部分应用程序后端 并用 Qt4 编写 GUI 我计划使用 Make 作为我的构建系统 这将是一个只有两名开发人员的项目 一旦我相对深入地了解它
  • CUDA 5.0错误LNK2001:cuda方法无法解析的外部符号

    我的链接器有错误 1 gt ManifestResourceCompile 1 gt All outputs are up to date 1 gt kernel cu obj error LNK2001 unresolved extern
  • cudaDeviceScheduleBlockingSync 和 cudaDeviceScheduleYield 之间有什么区别?

    正如这里所说 如何减少 CUDA 同步延迟 延迟 https stackoverflow com questions 11953722 how to reduce cuda synchronize latency delay 等待设备结果有
  • 设备内存刷新cuda

    我正在运行一个 C 程序 其中调用了两次 cuda 主机函数 我想清理这两个调用之间的设备内存 有没有办法可以刷新 GPU 设备内存 我使用的是计算能力为2 0的Tesla M2050 如果你只想将内存归零 那么cudaMemset可能是最
  • 如何在CUDA应用程序中正确应用线程同步?

    一般来说 我在应用程序中偶尔会使用线程同步 因为我并不经常需要此功能 我并不是真正的高级 C C 程序员 但我也不是初学者 我开始学习 CUDA C 对当今 GPU 与 CPU 的能力相比感到兴奋 我意识到 CUDA 编程主要是关于并行线程
  • 无法在 CUDA 中找到 1 到 100 数字的简单和?

    我正在研究使用 CUDA 的图像处理算法 在我的算法中 我想使用 CUDA 内核找到图像所有像素的总和 所以我在cuda中制作了内核方法 来测量16位灰度图像的所有像素的总和 但我得到了错误的答案 所以我在cuda中编写了一个简单的程序来查
  • 在 Cuda 中简单添加两个 int,结果始终相同

    我开始了学习Cuda的旅程 我正在玩一些 hello world 类型的 cuda 代码 但它不起作用 我不知道为什么 代码非常简单 取两个整数并将它们添加到 GPU 上并返回结果 但无论我将数字更改为什么 我都会得到相同的结果 如果数学那
  • CUDA 和 Eigen 的成员“已声明”错误

    我只是 CUDA 和 Nsight 的初学者 希望利用出色的 GPU 性能进行线性代数运算 例如 CUBLAS 我在以下人员的帮助下编写了很多自定义代码Eigen http eigen tuxfamily org index php tit
  • 如何在没有 nvcc 的情况下在编译时获取 CUDA 工具包版本?

    我在 cpp 文件中对 cuSPARSE 库进行了一些调用 这些调用在旧工具包中不可用 为了支持使用旧工具包的系统 我想使用编译器指令编译不同的代码部分 特别是 我想使用旧工具包的 CSR 格式矩阵和新工具包的 BSR 格式矩阵来求解稀疏三
  • 布尔实现的atomicCAS

    我想弄清楚是否存在错误答案 https stackoverflow com a 57444538 11248508 现已删除 关于Cuda like的实现atomicCAS for bool是 答案中的代码 重新格式化 static inl
  • 使用设备函数指针数组

    我需要以下设备版本 主机代码 double func double x double func1 double x return x 1 double func2 double x return x 2 double func3 doubl
  • 为什么在 CUDA 中启动 32 倍数的线程?

    我参加了 CUDA 并行编程课程 并且看到了许多 CUDA 线程配置的示例 其中通常将所需的线程数四舍五入到最接近的 32 倍数 我知道线程被分组为 warp 并且如果您启动 1000 个线程 GPU 无论如何都会将其四舍五入到 1024
  • 我可以将 CUDA 与非 NVIDIA GPU 一起使用吗? [复制]

    这个问题在这里已经有答案了 我正在寻找一种在没有 NVIDIA GPU 的系统上运行 CUDA 程序的方法 我尝试安装 MCUDA 和 gpuOcelot 但安装似乎遇到一些问题 我已经浏览了中给出的答案如何使用软件实现在没有 GPU 的情
  • 如何在 Java 编程中使用 GPU

    我这些天都在使用 CUDAC 来访问 GPU 但现在我的导游要求我使用 Java 和 GPU 于是我在网上搜索发现Rootbeer是最好的选择 但我无法理解如何使用 Rootbeer 运行程序 可以有一个吗告诉我使用 Rootbeer 的步

随机推荐