CUDA:如何在设备上填充动态大小的向量并将其内容返回到另一个设备函数?

2024-04-12

我想知道哪种技术可以填充设备上的动态大小数组(int *row,在下面的代码中),然后返回其内容,以供另一个设备函数使用。

为了将问题置于上下文中,下面的代码尝试使用在 GPU 上运行的高斯-勒让德求积来跨越勒让德多项式基组中的任意函数。

#include <math.h>
#include <stdlib.h>
#include <stdio.h>

__device__  double *d_droot, *d_dweight;

/*How could be returned the array or the pointer to the array int *row, on the device,  that is filled by this function? */
__device__
void Pascal_Triangle(int n_row, int * row) {

  int a[100][100];
  int i, j;

  //first row and first coloumn has the same value=1
  for (i = 1; i <= n_row; i++) {
    a[i][1] = a[1][i] = 1;
  }

  //Generate the full Triangle
  for (i = 2; i <= n_row; i++) {
    for (j = 2; j <= n_row - i; j++) {
      if (a[i - 1][j] == 0 || a[i][j - 1] == 0) {
    break;
      }
      a[i][j] = a[i - 1][j] + a[i][j - 1];
    }
  }

  row = new int[n_row];

  for (i = 1; i <= n_row; i++) {
    row[i] = a[i][n_row-1];
  }

}


__device__
double Legendre_poly(int order, double x)
{
  int n,k;
  double val=0;
  int *binomials;
  for(n=order; n>=0; n--)
    {
      Pascal_Triangle(n, binomials); /*Here are the problems*/
      for(k=0; k<=n; k++)
    val += binomials[k]*pow(x-1,n-k)*pow(x-1,k);
    }

  return val;
}


__device__ __host__
double f(double alpha,double x)
{
  /*function expanded on a basis of Legendre palynomials. */
  return exp(-alpha*x*x);
}


/*Kernel that computes the expansion by quadratures*/
__global__ void Span(int n, double alpha, double a, double b, double *coefficients)
{
  /*
    Parameters:
    n: Total number of expansion coeficients
    a: Upper integration limit
    b: Lower integration limit
    d_droots[]: roots for the quadrature
    d_dweight[]: weights for the quadrature
    coefficients[]: allocate N expansion coefficients.
  */

  double c1 = (b - a) / 2, c2 = (b + a) / 2, sum = 0;
  int dummy;

  int i = blockIdx.x*blockDim.x + threadIdx.x;
  if (i < n)
    {
      coefficients[i] = 0.0;
      for (dummy = 0; dummy < 5; dummy++)
    coefficients[i] += d_dweight[dummy] * f(alpha,c1 * d_droot[dummy] + c2)*Legendre_poly(dummy,c1 * d_droot[dummy] + c2)*c1;
    }

}


int main(void)
{
  int N = 1<<23;
  int N_nodes = 5;


  double *droot, *dweight, *dresult, *d_dresult, *d_droot_temp, *d_dweight_temp;


  /*double version in host*/
  droot =(double*)malloc(N_nodes*sizeof(double));
  dweight =(double*)malloc(N_nodes*sizeof(double));
  dresult =(double*)malloc(N*sizeof(double)); /*will recibe the results of N quadratures!*/


  /*double version in device*/
  cudaMalloc(&d_droot_temp, N_nodes*sizeof(double));
  cudaMalloc(&d_dweight_temp, N_nodes*sizeof(double));
  cudaMalloc(&d_dresult, N*sizeof(double)); /*results for N quadratures will be contained here*/


  /*double version of the roots and weights*/
  droot[0] = 0.90618;
  droot[1] = 0.538469;
  droot[2] = 0.0;
  droot[3] = -0.538469;
  droot[4] = -0.90618;


  dweight[0] = 0.236927;
  dweight[1] = 0.478629;
  dweight[2] = 0.568889;
  dweight[3] = 0.478629;
  dweight[4] = 0.236927;



  /*double copy host-> device*/
  cudaMemcpy(d_droot_temp, droot, N_nodes*sizeof(double), cudaMemcpyHostToDevice);
  cudaMemcpy(d_dweight_temp, dweight, N_nodes*sizeof(double), cudaMemcpyHostToDevice);
  cudaMemcpyToSymbol(d_droot, &d_droot_temp, sizeof(double *));
  cudaMemcpyToSymbol(d_dweight, &d_dweight_temp, sizeof(double *));

  // Perform the expansion

  Span<<<(N+255)/256, 256>>>(N,1.0,  -3.0, 3.0, d_dresult); /*This kerlnel works OK*/






  cudaMemcpy(dresult, d_dresult, N*sizeof(double), cudaMemcpyDeviceToHost);



  cudaFree(d_dresult);
  cudaFree(d_droot_temp);
  cudaFree(d_dweight_temp);

}

这是编译上面代码的 makefile:

objects = main.o 

all: $(objects)
        nvcc   -arch=sm_20 $(objects) -o span

%.o: %.cpp
        nvcc -x cu -arch=sm_20  -I. -dc $< -o $@

clean:
        rm -f *.o span

在此先感谢您的任何建议。


(抱歉我之前的回答有失偏颇)

你正在通过一个row指向该函数的指针:

void Pascal_Triangle(int n_row, int * row) {

然后,您尝试用新值覆盖该指针:

row = new int[n_row];

一旦你从这个函数返回,row在调用环境中将不会被修改。 (这是一个普通的 C/C++ 问题,并非 CUDA 特有的问题。)

这或许是一个令人困惑的问题,但指针值 of row已通过by value到函数Pascal_Triangle。您不能修改函数中的指针值,并期望修改后的值显示在调用环境中。 (你can修改指针指向的位置的内容,这是传递的常见原因row通过指针。)

有几种方法可以解决这个问题。最简单的可能只是通过引用传递指针:

void Pascal_Triangle(int n_row, int * &row) {

您的代码似乎还有其他缺陷。我建议你雇用正确的cuda错误检查 https://stackoverflow.com/questions/14038589/what-is-the-canonical-way-to-check-for-errors-using-the-cuda-runtime-api并运行你的代码cuda-memcheck.

特别是,内核中new运算符的行为方式与内核中类似malloc,并且它有类似的限制 http://docs.nvidia.com/cuda/cuda-c-programming-guide/index.html#dynamic-global-memory-allocation-and-operations.

您的设备堆空间即将耗尽,因此您的许多new操作失败,并返回 NULL 指针。

作为对此的测试,在您的代码之后放置这样的行是很好的调试实践new手术:

if (row == NULL) assert(0);

(您还需要包括assert.h)

如果你这样做,你会发现这个断言被命中了。

我还没有计算出您的代码实际需要多少设备堆空间,但它似乎使用了相当多的空间。在C++中,习惯上是delete的分配由new一旦你完成了它。您可能想研究释放使用以下命令完成的分配new,或者(甚至更好)重新使用分配(即每个线程分配一次),并完全避免重新分配。

这是对代码的修改,演示了上述内容(每个线程一个分配),并且编译和运行对我来说没有错误:

#include <math.h>
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>

__device__  double *d_droot, *d_dweight;

/*How could be returned the array or the pointer to the array int *row, on the device,  that is filled by this function? */
__device__
void Pascal_Triangle(int n_row, int *row) {

  int a[100][100];
  int i, j;

  //first row and first coloumn has the same value=1
  for (i = 1; i <= n_row; i++) {
    a[i][1] = a[1][i] = 1;
  }

  //Generate the full Triangle
  for (i = 2; i <= n_row; i++) {
    for (j = 2; j <= n_row - i; j++) {
      if (a[i - 1][j] == 0 || a[i][j - 1] == 0) {
    break;
      }
      a[i][j] = a[i - 1][j] + a[i][j - 1];
    }
  }

  for (i = 1; i <= n_row; i++) {
    row[i] = a[i][n_row-1];
  }

}


__device__
double Legendre_poly(int order, double x, int *my_storage)
{
  int n,k;
  double val=0;
  int *binomials = my_storage;
  if (binomials == NULL) assert(0);
  for(n=order; n>=0; n--)
    {
      Pascal_Triangle(n, binomials); /*Here are the problems*/
      for(k=0; k<=n; k++)
    val += binomials[k]*pow(x-1,n-k)*pow(x-1,k);
    }
  return val;
}


__device__ __host__
double f(double alpha,double x)
{
  /*function expanded on a basis of Legendre palynomials. */
  return exp(-alpha*x*x);
}


/*Kernel that computes the expansion by quadratures*/
__global__ void Span(int n, double alpha, double a, double b, double *coefficients)
{
  /*
    Parameters:
    n: Total number of expansion coeficients
    a: Upper integration limit
    b: Lower integration limit
    d_droots[]: roots for the quadrature
    d_dweight[]: weights for the quadrature
    coefficients[]: allocate N expansion coefficients.
  */

  double c1 = (b - a) / 2, c2 = (b + a) / 2, sum = 0;
  int dummy;

  int i = blockIdx.x*blockDim.x + threadIdx.x;
  if (i < n)
    {
      #define MY_LIM 5
      int *thr_storage = new int[MY_LIM];
      if (thr_storage == NULL) assert(0);
      coefficients[i] = 0.0;
      for (dummy = 0; dummy < MY_LIM; dummy++)
        coefficients[i] += d_dweight[dummy] * f(alpha,c1 * d_droot[dummy] + c2)*Legendre_poly(dummy,c1 * d_droot[dummy] + c2, thr_storage)*c1;
      delete thr_storage;
    }

}


int main(void)
{
  cudaDeviceSetLimit(cudaLimitMallocHeapSize, (1048576ULL*1024));
  int N = 1<<23;
  int N_nodes = 5;


  double *droot, *dweight, *dresult, *d_dresult, *d_droot_temp, *d_dweight_temp;


  /*double version in host*/
  droot =(double*)malloc(N_nodes*sizeof(double));
  dweight =(double*)malloc(N_nodes*sizeof(double));
  dresult =(double*)malloc(N*sizeof(double)); /*will recibe the results of N quadratures!*/


  /*double version in device*/
  cudaMalloc(&d_droot_temp, N_nodes*sizeof(double));
  cudaMalloc(&d_dweight_temp, N_nodes*sizeof(double));
  cudaMalloc(&d_dresult, N*sizeof(double)); /*results for N quadratures will be contained here*/


  /*double version of the roots and weights*/
  droot[0] = 0.90618;
  droot[1] = 0.538469;
  droot[2] = 0.0;
  droot[3] = -0.538469;
  droot[4] = -0.90618;


  dweight[0] = 0.236927;
  dweight[1] = 0.478629;
  dweight[2] = 0.568889;
  dweight[3] = 0.478629;
  dweight[4] = 0.236927;



  /*double copy host-> device*/
  cudaMemcpy(d_droot_temp, droot, N_nodes*sizeof(double), cudaMemcpyHostToDevice);
  cudaMemcpy(d_dweight_temp, dweight, N_nodes*sizeof(double), cudaMemcpyHostToDevice);
  cudaMemcpyToSymbol(d_droot, &d_droot_temp, sizeof(double *));
  cudaMemcpyToSymbol(d_dweight, &d_dweight_temp, sizeof(double *));

  // Perform the expansion

  Span<<<(N+255)/256, 256>>>(N,1.0,  -3.0, 3.0, d_dresult); /*This kerlnel works OK*/






  cudaMemcpy(dresult, d_dresult, N*sizeof(double), cudaMemcpyDeviceToHost);



  cudaFree(d_dresult);
  cudaFree(d_droot_temp);
  cudaFree(d_dweight_temp);

}

这段代码有几个优点:

  1. 它可以在设备堆上以更小的保留运行
  2. 它比您的代码尝试执行的大量分配要快得多。

EDIT:

而不是assert你可以这样做:

/*Kernel that computes the expansion by quadratures*/
__global__ void Span(int n, double alpha, double a, double b, double *coefficients)
{
  /*
    Parameters:
    n: Total number of expansion coeficients
    a: Upper integration limit
    b: Lower integration limit
    d_droots[]: roots for the quadrature
    d_dweight[]: weights for the quadrature
    coefficients[]: allocate N expansion coefficients.
  */

  double c1 = (b - a) / 2, c2 = (b + a) / 2, sum = 0;
  int dummy;

  int i = blockIdx.x*blockDim.x + threadIdx.x;
  if (i < n)
    {
      #define MY_LIM 5
      int *thr_storage = new int[MY_LIM];
      if (thr_storage == NULL) printf("allocation failure!\");
      else {
        coefficients[i] = 0.0;
        for (dummy = 0; dummy < MY_LIM; dummy++)
          coefficients[i] += d_dweight[dummy] * f(alpha,c1 * d_droot[dummy] + c2)*Legendre_poly(dummy,c1 * d_droot[dummy] + c2, thr_storage)*c1;
        delete thr_storage;
        }
    }

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

CUDA:如何在设备上填充动态大小的向量并将其内容返回到另一个设备函数? 的相关文章

  • 调用许多网络服务的最佳方式?

    我有 30 家子公司 每家都实施了他们的 Web 服务 使用不同的技术 我需要实现一个Web服务来聚合它们 例如 所有子公司的Web服务都有一个名为的Web方法GetUserPoint int nationalCode 我需要实现我的网络服
  • 内联 PTX 汇编代码强大吗?

    我看到一些代码示例 人们在 C 代码中使用内联 PTX 汇编代码 CUDA工具包中的文档提到PTX很强大 为什么会这样呢 如果我们在 C 代码中使用这样的代码 我们会得到什么好处 内联 PTX 使您可以访问未通过 CUDA 内在函数公开的指
  • 当从后台工作程序发生事件时,XlCall.Excel(XlCall.xlcCalculateNow) 抛出 XlCallException

    我有一个 ExcelFunction 来排队一些计算 ExcelFunction public static void QueueCalcs takes ranges var calcRequests builds list of calc
  • std::list::clear 是否会使 std::list::end 迭代器无效?

    检查这个代码 include stdafx h include
  • 从 Invoke 方法获取 RETURN

    我正在尝试从另一个线程上的列表框项目中读取值 我尝试创建一种新方法来运行调用命令 我可以设法将命令发送到列表框 例如通过调用方法添加 但我似乎无法得到响应 我似乎无法获取该项目的值 我尝试了几种方法 一旦我将它从空变为字符串 事情就开始变得
  • 通过 SOAP 的 Gmt php 或 UTC C# 等效项

    is C DateTime UtcNow和 PHPdate c 是等价的 我怀疑 因为当我肥皂时 我得到了 C
  • C# 和月历,选择多个日期

    我正在制作一个程序 可以帮助人们用 C 为某个部门 预订 订单 他们需要能够选择不同月份的多个日期 我更愿意拥有它 这样他们就可以单击一个日期 然后按住 Shift 键单击另一个日期以选择这两个日期之间的所有日期 并控制单击以进行单选 取消
  • C# Outlook 从收件人获取 CompanyName 属性

    我目前正在使用 C 编写 Outlook 2010 AddIn 我想要的是从我从 AppointmentItem 中提取的 Recipient 对象中获取 CompanyName 属性 因此 有了 AppointmentItem 的收件人
  • 具有多个谓词的 C++11 算法

    功能如std find if来自algorithmheader 确实很有用 但对我来说 一个严重的限制是我只能为每次调用使用 1 个谓词count if 例如给定一个像这样的容器std vector我想同时应用相同的迭代find if 多个
  • MSMQ接收和删除

    是否有任何选项可以在读取消息后将其从 MSMQ 中删除 比如 接收 删除可以作为原子操作运行吗 听起来您想查看下一条消息 然后在处理完成后接收它 Message message Queue Peek Queue ReceiveById me
  • “没有合适的默认构造函数可用”——为什么会调用默认构造函数?

    我已经查看了与此相关的其他一些问题 但我不明白为什么在我的情况下甚至应该调用默认构造函数 我可以只提供一个默认构造函数 但我想了解它为什么这样做以及它会产生什么影响 error C2512 CubeGeometry no appropria
  • 如何设置消息队列的所有者?

    System Messaging MessageQueue 类不提供设置队列所有权的方法 如何以编程方式设置 MSMQ 消息队列的所有者 简短的答案是 p invoke 对 windows api 函数的调用MQSetQueueSecuri
  • 是否可以在Linux上将C转换为asm而不链接libc?

    测试平台为Linux 32位 但也欢迎 Windows 32 位上的某些解决方案 这是一个c代码片段 int a 0 printf d n a 如果我使用 gcc 生成汇编代码 gcc S test c 然后我会得到 movl 0 28 e
  • 如何在 EF Core 2.1 中定义外键关系

    我的 DAL 使用 EF Core 2 1 这就是我的模型的样子 一名用户只能拥有一种角色 Role entity kind of master public class Role public int RoleId get set pub
  • 如何对STL向量进行排序?

    我想排序一个vector vector
  • 如何测试某些代码在 C++ 中无法编译? [复制]

    这个问题在这里已经有答案了 可能的重复 单元测试编译时错误 https stackoverflow com questions 605915 unit test compile time error 我想知道是否可以编写一种单元测试来验证给
  • 时间:2019-03-17 标签:c#TimerStopConfusion

    我想通过单击按钮时更改文本颜色来将文本框文本设置为 闪烁 我可以让文本按照我想要的方式闪烁 但我希望它在闪烁几次后停止 我不知道如何在计时器触发几次后让它停止 这是我的代码 public Form1 InitializeComponent
  • 在 C 中使用 #define 没有任何价值

    If a define没有任何价值地使用 例如 define COMMAND SPI 默认值是0吗 不 它的评估结果为零 从字面上看 该符号被替换为空 然而 一旦你有了 define FOO 预处理器条件 ifdef FOO现在将是真的 另
  • Unity,c++ 本机插件字节数组不匹配

    在我的 C 本机插件中 我有一个调用 vector
  • Emacs C++,打开相应的头文件

    我是 emacs 新手 我想知道 是否有在头文件 源文件和相应的源文件 头文件之间切换的快捷方式 是否有像通用 emacs 参考卡那样的参考卡 Thanks There s ff find other file 您可以使用以下方法将其绑定到

随机推荐

  • 通过环境变量告诉 ld 在哪里查找目录

    我正在对课程的 C 和 C 文件进行评分 并且此作业使用 GSL 库 由于我的计算机没有 root 权限 因此我的 GSL 库安装在我的主目录中 因此我需要告诉编译器和链接器在哪里可以找到它 当我自己编写程序时 这不是问题 因为我只需向 g
  • 按字典值对字典列表进行排序

    我有以下字典列表 a 23 100 3 103 2 102 36 103 43 123 我如何对其进行排序以获得 a 43 123 3 103 36 103 2 102 23 100 我的意思是 按字典值对列表进行降序排序 除了brandi
  • Puppeteer - 如何使用 page.evaluateHandle

    我在使用最新版本的 puppeteer 时遇到一些问题 我正在使用 puppeteer 版本 0 13 0 我有一个包含此元素的网站 div class header hey there div 我正在尝试运行这段代码 const head
  • 在 boost 几何体中创建实心多边形

    我是增强几何的新手 我已经创建了多边形boost geometry assign points 但我只创建该多边形的外部和内部是空的 所以我尝试测试boost geometry overlaps 两个多边形 A B 且 A 在 B 内部 结
  • Mysql按分钟查询、选择、分组、求和

    我有一个像这样的数据库表 id donation type donation amount time inserted 1 em1 20 2012 12 07 10 01 00 2 em1 50 2012 12 07 10 01 00 3
  • 如何使用 Java 开发 iPhone 应用程序? [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我想知道是否可以使用 Java 加 XMLV 来开发 iPhone 应用程序 XMLV 声称可以将基于 Java 的 Android
  • jquery-ajax 多次调用

    我使用以下代码来发出多个 ajax 请求 如下所示 request 1 start 要求1 finish 要求2 start 要求2 finish 这是代码 var startingpoint fireRequest 1 each type
  • 如何将清单信息添加到delphi项目中

    添加最简单的方法是什么
  • 如何在 Haskell 中使用 TypeApplications?

    With XTypeApplications在 GHC 8 0 中 您可以使用显式指定类型 前面的函数参数 它到底指定了什么类型 尤其是当有多个类型时 有介绍吗 如果你看一下函数的类型 elem Foldable t Eq a gt a g
  • 适用于 Android/Java 的“自从/以前的时间”库 [关闭]

    Closed 此问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 对于 Android Java 显示时间的好库有什么建议吗 例如 10 分钟前 5 天前 来自 Goog
  • 多个目标名称具有相同的动画

    只是一个疑问 我的 WPF 应用程序中有三个图像 我将为这三个图像提供闪烁效果 所以我给出了这段代码
  • 多个等待与 Task.WaitAll - 等效吗?

    从性能上来说 这2个方法会跑吗GetAllWidgets and GetAllFoos 在平行下 有什么理由使用其中一种而不是另一种吗 编译器在幕后似乎发生了很多事情 所以我不清楚 方法A 使用多个等待 public async Task
  • 重定向 PHP [重复]

    这个问题在这里已经有答案了 如何从 PHP 页面重定向到另一个页面 div div a href login html class ui btn left Back a div div
  • 根据旋转角度计算XY运动?

    假设我在 2D 空间中有一个可以旋转的对象 然后应该根据其旋转角度移动 例如 如果角度为0 指向上方 则on timer它应该将 1 移动 Y 将 0 移动 X 如果角度为 45 那么它应该按 Y 移动 1 按 X 移动 1 如果指向 90
  • 使用 Postgresql 让 Sqlalchemy 在过滤器中使用日期

    我正在尝试在 Sqlalchemy 中执行以下查询 Select from Mytable where Date date time field 2011 08 16 我尝试了几种方法 有些在这里 但没有一个看起来 现实 因为有些确实强制转
  • Python urllib2:即使在 HTTPError 异常期间也读取内容主体?

    我正在使用 urllib2 通过 HTTP 获取页面 有时 当我的请求包含错误时 资源会抛出 HTTP 错误 400 错误请求 但是 该响应还包含一个提供详细错误消息的 XML 元素 能够看到该错误而不仅仅是 urllib2 返回的 HTT
  • getResourceAsStream(file) 在哪里搜索文件?

    我很困惑getResourceAsStream 我的包结构如下 src net floodlightcontroller invoked getResourceAsStream here resources floodlightdefaul
  • 查找mysql死锁原因

    1 我有一个脚本 执行一些更新 删除操作 2 所有sql操作都在事务内执行 InnoDb表 3 有时我会收到 尝试获取锁定时发现死锁 尝试重新启动事务 该应用程序中还有一些其他作业执行数据库操作 我的问题是找出其他脚本中的哪些并发查询会干扰
  • 如何使用 Apache SOLR 和 PHP 代码突出显示搜索结果

    我使用 SOLR 和 Tomcat servlet 容器开发了搜索页面 使用 PHP 代码 我将搜索查询发布到 solrQuery 函数中 并在此函数中定义了查询参数 如下所示 query q trim urlencode q versio
  • CUDA:如何在设备上填充动态大小的向量并将其内容返回到另一个设备函数?

    我想知道哪种技术可以填充设备上的动态大小数组 int row 在下面的代码中 然后返回其内容 以供另一个设备函数使用 为了将问题置于上下文中 下面的代码尝试使用在 GPU 上运行的高斯 勒让德求积来跨越勒让德多项式基组中的任意函数 incl