3D 数组作为纹理在 CUDA 中写入和读取

2024-03-01

由于我正在编程的算法的性质,我需要用一些特定的数学写入/填充 3D 矩阵,然后从该矩阵(在单独的内核中)读取作为 3D 线性插值纹理。

由于纹理是一种读取模式,我假设我可以以某种方式在绑定到纹理的全局内存中写入,并从中单独读取,而不需要双倍内存并将值从写入复制到读取矩阵。但是我似乎不知道如何做到这一点。

  • 如何使用 3D 纹理内存进行读取和写入(在单独的内核中)?

我的问题是我不知道如何定义这个全局读/写数组。在下面的示例中,我创建了一个 3D 纹理,但这是使用带有以下代码的代码cudaExtent and cudaArray。但我似乎无法使用这种类型在它们上书写,我似乎也无法使用创建它们float*或喜欢的。

我可能无法做到这一点并且需要memcpy中间的某个地方,但由于这些数组通常很大,我想节省内存。

示例代码(无法编译,但清楚地定义了我想要做的事情的结构)。默认使用 100x100x100 3D 内存,因为是的。

#include "cuda_runtime.h"
#include "device_launch_parameters.h"
#include <cuda_runtime_api.h>
#include <cuda.h>

#define MAXTREADS 1024

cudaError_t addWithCuda(int *c, const int *a, const int *b, unsigned int size);
texture<float, cudaTextureType3D, cudaReadModeElementType> tex;

__global__ void readKernel(float* imageend )
{
    int indY = blockIdx.y * blockDim.y + threadIdx.y;
    int indX = blockIdx.x * blockDim.x + threadIdx.x;
    int indZ = blockIdx.z * blockDim.z + threadIdx.z;
    //Make sure we dont go out of bounds
    size_t idx = indZ * 100 * 100 + indY * 100 + indX;
    if (indX >= 100 | indY >= 100 | indZ >= 100)
        return;
    imageend[idx] = tex3D(tex, indX + 0.5, indY + 0.5, indZ + 0.5);

}
__global__ void writeKernel(float* imageaux){
    int indY = blockIdx.y * blockDim.y + threadIdx.y;
    int indX = blockIdx.x * blockDim.x + threadIdx.x;
    int indZ = blockIdx.z * blockDim.z + threadIdx.z;
    //Make sure we dont go out of bounds
    size_t idx = indZ * 100 * 100 + indY * 100 + indX;
    if (indX >= 100 | indY >= 100 | indZ >= 100)
        return;
    imageaux[idx] = (float)idx;

}
int main()
{

    cudaArray *d_image_aux= 0;
    const cudaExtent extent = make_cudaExtent(100, 100, 100);
    cudaChannelFormatDesc channelDesc = cudaCreateChannelDesc<float>();
    cudaMalloc3DArray(&d_image_aux, &channelDesc, extent);

    // Configure texture options
    tex.normalized = false;
    tex.filterMode = cudaFilterModeLinear;
    tex.addressMode[0] = cudaAddressModeBorder;
    tex.addressMode[1] = cudaAddressModeBorder;
    tex.addressMode[2] = cudaAddressModeBorder;

    cudaBindTextureToArray(tex, d_image_aux, channelDesc);

    float *d_image_end = 0;
    size_t num_bytes = 100 * 100 * 100 * sizeof(float);
    cudaMalloc((void**)&d_image_end, num_bytes);
    cudaMemset(d_image_end, 0, num_bytes);

    int divx, divy, divz; //Irrelevant for the demo, important for the main code
    divx = 32;
    divy = 32;
    divz = 1;
    dim3 grid((100 + divx - 1) / divx,
        (100 + divy - 1) / divy,
        (100 + divz - 1) / divz);
    dim3 block(divx, divy, divz);

    // Kernels
    writeKernel << <grid, block >> >(d_image_aux);
    readKernel  << <grid, block >> >(d_image_end);


    cudaUnbindTexture(tex);
    cudaFree(d_image_aux);
    cudaFree(d_image_end);

    return 0;
}

NOTE:我知道我不能写“插值”或其他任何内容。写入操作将始终采用整数索引,而读取操作则需要使用三线性插值。


我相信所有必要的部分都可以演示内核写入 3D 表面(绑定到底层 3D cudaArray),然后是来自相同数据(绑定到相同底层 3D 的 3D 纹理)的另一个内核纹理(即自动插值) cudaArray)包含在体积过滤 CUDA 示例代码 http://docs.nvidia.com/cuda/cuda-samples/index.html#volumetric-filtering-with-3d-textures-and-surface-writes.

唯一的概念差异是示例代码有 2 个不同的底层 3D cudaArray(一个用于纹理,一个用于表面),但我们可以将它们组合起来,以便随后在纹理操作期间读取写入表面的数据。

这是一个完整的示例:

$ cat texsurf.cu
#include <stdio.h>
#include <helper_cuda.h>

texture<float, cudaTextureType3D, cudaReadModeElementType>  volumeTexIn;
surface<void,  3>                                    volumeTexOut;

__global__ void
surf_write(float *data,cudaExtent volumeSize)
{
    int x = blockIdx.x*blockDim.x + threadIdx.x;
    int y = blockIdx.y*blockDim.y + threadIdx.y;
    int z = blockIdx.z*blockDim.z + threadIdx.z;

    if (x >= volumeSize.width || y >= volumeSize.height || z >= volumeSize.depth)
    {
        return;
    }
    float output = data[z*(volumeSize.width*volumeSize.height)+y*(volumeSize.width)+x];
    // surface writes need byte offsets for x!
    surf3Dwrite(output,volumeTexOut,x * sizeof(float),y,z);

}

__global__ void
tex_read(float x, float y, float z){
    printf("x: %f, y: %f, z:%f, val: %f\n", x,y,z,tex3D(volumeTexIn,x,y,z));
}

void runtest(float *data, cudaExtent vol, float x, float y, float z)
{
    // create 3D array
    cudaChannelFormatDesc channelDesc = cudaCreateChannelDesc<float>();
    cudaArray_t content;
    checkCudaErrors(cudaMalloc3DArray(&content, &channelDesc, vol, cudaArraySurfaceLoadStore));

    // copy data to device
    float *d_data;
    checkCudaErrors(cudaMalloc(&d_data, vol.width*vol.height*vol.depth*sizeof(float)));
    checkCudaErrors(cudaMemcpy(d_data, data, vol.width*vol.height*vol.depth*sizeof(float), cudaMemcpyHostToDevice));

    dim3 blockSize(8,8,8);
    dim3 gridSize((vol.width+7)/8,(vol.height+7)/8,(vol.depth+7)/8);
    volumeTexIn.filterMode     = cudaFilterModeLinear;
    checkCudaErrors(cudaBindSurfaceToArray(volumeTexOut,content));
    surf_write<<<gridSize, blockSize>>>(d_data, vol);
    // bind array to 3D texture
    checkCudaErrors(cudaBindTextureToArray(volumeTexIn, content));
    tex_read<<<1,1>>>(x, y, z);
    checkCudaErrors(cudaDeviceSynchronize());
    cudaFreeArray(content);
    cudaFree(d_data);
    return;
}

int main(){
   const int dim = 8;
   float *data = (float *)malloc(dim*dim*dim*sizeof(float));
   for (int z = 0; z < dim; z++)
     for (int y = 0; y < dim; y++)
       for (int x = 0; x < dim; x++)
         data[z*dim*dim+y*dim+x] = z*100+y*10+x;
   cudaExtent vol = {dim,dim,dim};
   runtest(data, vol, 1.5, 1.5, 1.5);
   runtest(data, vol, 1.6, 1.6, 1.6);
   return 0;
}


$ nvcc -I/usr/local/cuda/samples/common/inc texsurf.cu -o texsurf
$ cuda-memcheck ./texsurf
========= CUDA-MEMCHECK
x: 1.500000, y: 1.500000, z:1.500000, val: 111.000000
x: 1.600000, y: 1.600000, z:1.600000, val: 122.234375
========= ERROR SUMMARY: 0 errors
$

我不会尝试在这里提供有关线性纹理过滤的完整教程。这里还有很多其他示例问题,涵盖了索引和过滤的细节,但这似乎不是这个问题的关键。我选择了点 (1.5, 1.5, 1.5) 和 (1.6, 1.6, 1.6) 以便于验证基础数据;结果对我来说很有意义。

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

3D 数组作为纹理在 CUDA 中写入和读取 的相关文章

  • 如何使用 C# 中的参数将用户重定向到 paypal

    如果我有像下面这样的简单表格 我可以用它来将用户重定向到 PayPal 以完成付款
  • 我如何才能等待多个事情

    我正在使用 C 11 和 stl 线程编写一个线程安全队列 WaitAndPop 方法当前如下所示 我希望能够将一些内容传递给 WaitAndPop 来指示调用线程是否已被要求停止 如果 WaitAndPop 等待并返回队列的元素 则应返回
  • 不支持将数据直接绑定到存储查询(DbSet、DbQuery、DbSqlQuery)

    正在编码视觉工作室2012并使用实体模型作为我的数据层 但是 当页面尝试加载时 上面提到的标题 我使用 Linq 语句的下拉控件往往会引发未处理的异常 下面是我的代码 using AdventureWorksEntities dw new
  • 用于检查类是否具有运算符/成员的 C++ 类型特征[重复]

    这个问题在这里已经有答案了 可能的重复 是否可以编写一个 C 模板来检查函数是否存在 https stackoverflow com questions 257288 is it possible to write a c template
  • 如何使用 ICU 解析汉字数字字符?

    我正在编写一个使用 ICU 来解析由汉字数字字符组成的 Unicode 字符串的函数 并希望返回该字符串的整数值 五 gt 5 三十一 gt 31 五千九百七十二 gt 5972 我将区域设置设置为 Locale getJapan 并使用
  • 在 Windows 窗体中保存带有 Alpha 通道的单色位图会保存不同(错误)的颜色

    在 C NET 2 0 Windows 窗体 Visual Studio Express 2010 中 我保存由相同颜色组成的图像 Bitmap bitmap new Bitmap width height PixelFormat Form
  • HTTPWebResponse 响应字符串被截断

    应用程序正在与 REST 服务通信 Fiddler 显示作为 Apps 响应传入的完整良好 XML 响应 该应用程序位于法属波利尼西亚 在新西兰也有一个相同的副本 因此主要嫌疑人似乎在编码 但我们已经检查过 但空手而归 查看流读取器的输出字
  • 使用 WebClient 时出现 System.Net.WebException:无法创建 SSL/TLS 安全通道

    当我执行以下代码时 System Net ServicePointManager ServerCertificateValidationCallback sender certificate chain errors gt return t
  • C++ OpenSSL 导出私钥

    到目前为止 我成功地使用了 SSL 但遇到了令人困惑的障碍 我生成了 RSA 密钥对 之前使用 PEM write bio RSAPrivateKey 来导出它们 然而 手册页声称该格式已经过时 实际上它看起来与通常的 PEM 格式不同 相
  • WCF 中 SOAP 消息的数字签名

    我在 4 0 中有一个 WCF 服务 我需要向 SOAP 响应添加数字签名 我不太确定实际上应该如何完成 我相信响应应该类似于下面的链接中显示的内容 https spaces internet2 edu display ISWG Signe
  • 转发声明和包含

    在使用库时 无论是我自己的还是外部的 都有很多带有前向声明的类 根据情况 相同的类也包含在内 当我使用某个类时 我需要知道该类使用的某些对象是前向声明的还是 include d 原因是我想知道是否应该包含两个标题还是只包含一个标题 现在我知
  • Windows 窗体:如果文本太长,请添加新行到标签

    我正在使用 C 有时 从网络服务返回的文本 我在标签中显示 太长 并且会在表单边缘被截断 如果标签不适合表单 是否有一种简单的方法可以在标签中添加换行符 Thanks 如果您将标签设置为autosize 它会随着您输入的任何文本自动增长 为
  • WPF/C# 将自定义对象列表数据绑定到列表框?

    我在将自定义对象列表的数据绑定到ListBox in WPF 这是自定义对象 public class FileItem public string Name get set public string Path get set 这是列表
  • 为什么编译时浮点计算可能不会得到与运行时计算相同的结果?

    In the speaker mentioned Compile time floating point calculations might not have the same results as runtime calculation
  • cmake 将标头包含到每个源文件中

    其实我有一个简单的问题 但找不到答案 也许你可以给我指一个副本 所以 问题是 是否可以告诉 cmake 指示编译器在每个源文件的开头自动包含一些头文件 这样就不需要放置 include foo h 了 谢谢 CMake 没有针对此特定用例的
  • C# - OutOfMemoryException 在 JSON 文件上保存列表

    我正在尝试保存压力图的流数据 基本上我有一个压力矩阵定义为 double pressureMatrix new double e Data GetLength 0 e Data GetLength 1 基本上 我得到了其中之一pressur
  • 如何在文本框中插入图像

    有没有办法在文本框中插入图像 我正在开发一个聊天应用程序 我想用图标图像更改值 等 但我找不到如何在文本框中插入图像 Thanks 如果您使用 RichTextBox 进行聊天 请查看Paste http msdn microsoft co
  • C++ 中类级 new 删除运算符的线程安全

    我在我的一门课程中重新实现了新 删除运算符 现在我正在使我的代码成为多线程 并想了解这些运算符是否也需要线程安全 我在某处读到 Visual Studio 中默认的 new delete 运算符是线程安全的 但这对于我的类的自定义 new
  • 如何防止用户控件表单在 C# 中处理键盘输入(箭头键)

    我的用户控件包含其他可以选择的控件 我想实现使用箭头键导航子控件的方法 问题是家长控制拦截箭头键并使用它来滚动其视图什么是我想避免的事情 我想自己解决控制内容的导航问题 我如何控制由箭头键引起的标准行为 提前致谢 MTH 这通常是通过重写
  • 使用.NET技术录制屏幕视频[关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 有没有一种方法可以使用 NET 技术来录制屏幕 无论是桌面还是窗口 我的目标是免费的 我喜欢小型 低

随机推荐

  • 与 java 一起使用的最佳数学库是什么? [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • 组合两个相等链表的转轮技术

    所以 我在这里面临着一个疑问 我正在读 破解编码面试 一书 那里写着下面的文字 假设你有一个链表a1 gt a2 gt an gt b1 gt b2 bn 并且您想将其重新排列为a1 gt b1 gt a2 gt b2 gt an gt b
  • 如何删除mongodb中的深层嵌套对象

    假设我有一个代表这样的书籍的文档 id 1234567890 title Lord Of The Rings books 1234567890 id 123456789890 title The Two Towers page count
  • 如何更改 wcf 客户端中的时间戳安全标头?

    我正在尝试修改安全标头的默认过期时间 即 5 分钟到 1 分钟 服务器的安全策略之一是时间戳 请求的日期 生存时间为一分钟 任何想法 我尝试创建自定义绑定但没有成功
  • ActiveAdmin 中的格式提示问题(不需要的对象 ID 输出)

    当我使用 formattastic DSL 进行 ActiveAdmin 编辑表单时 我得到以下输出 0x00000006bd1018 gt 图片标签 gt 为什么这从 obj inspect 的结果开始以及如何删除这部分 导致此错误的代码
  • 如何正确使用范围 https://www.googleapis.com/auth/drive.file

    我尝试使用以下代码访问我的 Google 云端硬盘中的 Google 表格文件 import gspread from oauth2client service account import ServiceAccountCredential
  • 我的 UITableViewController 中的内存泄漏在哪里?

    表视图工作正常 但是当我离开视图并第二次返回时 出现内存泄漏 可能 viewDidLoad 中的某些内容不确定 我正在运行泄漏工具并收到以下通知 Leaked Object Address Size Responsible Library
  • 在PyQt中,如何将终端嵌入到窗口中?

    我有一个小脚本 旨在将 xterm 嵌入 PyQt GUI 中 在 Linux 上 它可以工作 创建一个如下所示的 GUI 然而 在 OS X 上运行相同的脚本会产生两个如下所示的窗口 有谁知道如何解决这个问题并防止 OS X 搞砸 GUI
  • 我应该将变量保留为瞬态吗?

    我一直在尝试使用 Apache Spark 来解决一些查询 例如 top k skyline 等 我做了一个包装纸 其中包含SparkConf and JavaSparkContext named SparkContext 这个类也实现了可
  • 将标准输入和标准输出重定向到文件

    我目前是一个学校的助教C语言简介班级 该课程是使用 Visual Studio 进行教学的 但是在评分时 我只使用一个简单的 Windows 批处理脚本来处理所有提交的作业 编译它们 在测试文件上运行它们 并将输出重定向到我可以打印的一系列
  • ListView获取滚动位置?

    我正在使用 MergeAdapter 来自 Mark Murphy 的优秀项目系列 您可以将它与 ListView 一起使用 我试图在刷新时重建适配器的内容 而不是 就地 刷新并调用notifyDataSetChange 我想获取列表视图的
  • 在 R data.table 中,如何将变量参数传递给表达式?

    我遇到了一个 R 小问题data table 非常感谢您的帮助 我该怎么做呢 getResult lt function dt expr gby e lt substitute expr b lt substitute gby return
  • 使用 Excel VBA 重命名文件

    这就是我需要做的 我在 Excel 工作表中有这两列 带文件名 第一列包含当前文件名 第二列包含我想要将文件重命名为的名称 我需要使用它 因为重命名没有模式 例如 下面可能是一组文件 Current Name gt Rename To Ab
  • Scala中如何从内部类引用外部对象

    考虑这段代码 这是一种类型安全单元 abstract class UnitsZone type ConcreteUnit lt AbstractUnit abstract class AbstractUnit val qty Int SOM
  • simplexml_load_file 不起作用

    我下面有这段代码 它在我的远程托管服务器上运行良好 但由于某种原因不能在我的本地 Linux 机器上运行 我也尝试使用 file get contents 来获得宁静的服务 但它也返回 false 有谁知道为什么会发生这种情况 谢谢 xml
  • 使用“devtools::install_github”和克隆 GitHub 存储库有什么区别?

    I used devtools install github 在 R 中安装存储库 并使用以下命令安装了存储库git clone在终端 这两条路线有什么区别 到目前为止 我明白我可以使用library package 在 R 中 并将加载该
  • Angular 5中如何从父组件继承子组件中的CSS样式

    我有一个父组件 其中有一个子组件 父组件有一些 css 类 子组件扩展了它们 我尝试使用 host 查看文档 但似乎无法使其正常工作 子组件 div class table row body div class table cell bod
  • 对指针数组进行排序

    我是否正确地认为 为了对指针数组进行排序 将指针视为 int 是可以的 例如 qsort ptrs n sizeof void int cmp 我想对 ptr 进行排序以确定是否存在重复项 而不管指针指向的类型是什么 因此 qsort 是执
  • 如何调用shell脚本来启动后端Java进程?

    完成 Jenkins 任务后 我使用 Jenkins 的后置条件配置部分执行 Linux shell 脚本 这个 Linux shell 脚本想要在后端启动备用服务 并且不能导致 Jenkins 暂停 我尝试使用 nohup 等 但不起作用
  • 3D 数组作为纹理在 CUDA 中写入和读取

    由于我正在编程的算法的性质 我需要用一些特定的数学写入 填充 3D 矩阵 然后从该矩阵 在单独的内核中 读取作为 3D 线性插值纹理 由于纹理是一种读取模式 我假设我可以以某种方式在绑定到纹理的全局内存中写入 并从中单独读取 而不需要双倍内