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:如何在设备上填充动态大小的向量并将其内容返回到另一个设备函数? 的相关文章

  • 在模板类中声明模板友元类时出现编译器错误

    我一直在尝试实现我自己的链表类以用于教学目的 我在迭代器声明中指定了 List 类作为友元 但它似乎无法编译 这些是我使用过的 3 个类的接口 Node h define null Node
  • 调用 McAfee 病毒扫描引擎

    我收到客户的请求 要求使用他们服务器上的 McAfee 病毒扫描将病毒扫描集成到应用程序中 我做了一些调查 发现 McScan32 dll 是主要的扫描引擎 它导出各种看起来有用的函数 我还发现提到了 McAfee Scan Engine
  • STL 迭代器:前缀增量更快? [复制]

    这个问题在这里已经有答案了 可能的重复 C 中的预增量比后增量快 正确吗 如果是 为什么呢 https stackoverflow com questions 2020184 preincrement faster than postinc
  • 从经典 ASP 调用 .Net C# DLL 方法

    我正在开发一个经典的 asp 项目 该项目需要将字符串发送到 DLL DLL 会将其序列化并发送到 Zebra 热敏打印机 我已经构建了我的 DLL 并使用它注册了regasm其次是 代码库这使得 IIS 能够识别它 虽然我可以设置我的对象
  • 如何使从 C# 调用的 C(P/invoke)代码“线程安全”

    我有一些简单的 C 代码 它使用单个全局变量 显然这不是线程安全的 所以当我使用 P invoke 从 C 中的多个线程调用它时 事情就搞砸了 如何为每个线程单独导入此函数 或使其线程安全 我尝试声明变量 declspec thread 但
  • WPF 数据绑定到复合类模式?

    我是第一次尝试 WPF 并且正在努力解决如何将控件绑定到使用其他对象的组合构建的类 例如 如果我有一个由两个单独的类组成的类 Comp 为了清楚起见 请注意省略的各种元素 class One int first int second cla
  • 方程“a + bx = c + dy”的积分解

    在等式中a bx c dy 所有变量都是整数 a b c and d是已知的 我如何找到整体解决方案x and y 如果我的想法是正确的 将会有无限多个解 由最小公倍数分隔b and d 但我只需要一个解决方案 我可以计算其余的 这是一个例
  • 为什么这个字符串用AesCryptoServiceProvider第二次解密时不相等?

    我在 C VS2012 NET 4 5 中的文本加密和解密方面遇到问题 具体来说 当我加密并随后解密字符串时 输出与输入不同 然而 奇怪的是 如果我复制加密的输出并将其硬编码为字符串文字 解密就会起作用 以下代码示例说明了该问题 我究竟做错
  • 如何定义一个可结构化绑定的对象的概念?

    我想定义一个concept可以检测类型是否T can be 结构化绑定 or not template
  • C# xml序列化必填字段

    我需要将一些字段标记为需要写入 XML 文件 但没有成功 我有一个包含约 30 个属性的配置类 这就是为什么我不能像这样封装所有属性 public string SomeProp get return someProp set if som
  • 空指针与 int 等价

    Bjarne 在 C 编程语言 中写道 空指针与整数零不同 但 0 可以用作空指针的指针初始值设定项 这是否意味着 void voidPointer 0 int zero 0 int castPointer reinterpret cast
  • LINQ:使用 INNER JOIN、Group 和 SUM

    我正在尝试使用 LINQ 执行以下 SQL 最接近的是执行交叉联接和总和计算 我知道必须有更好的方法来编写它 所以我向堆栈团队寻求帮助 SELECT T1 Column1 T1 Column2 SUM T3 Column1 AS Amoun
  • 复制目录下所有文件

    如何将一个目录中的所有内容复制到另一个目录而不循环遍历每个文件 你不能 两者都不Directory http msdn microsoft com en us library system io directory aspx nor Dir
  • 相当于Linux中的导入库

    在 Windows C 中 当您想要链接 DLL 时 您必须提供导入库 但是在 GNU 构建系统中 当您想要链接 so 文件 相当于 dll 时 您就不需要链接 为什么是这样 是否有等效的 Windows 导入库 注意 我不会谈论在 Win
  • 为什么C++代码执行速度比java慢?

    我最近用 Java 编写了一个计算密集型算法 然后将其翻译为 C 令我惊讶的是 C 的执行速度要慢得多 我现在已经编写了一个更短的 Java 测试程序和一个相应的 C 程序 见下文 我的原始代码具有大量数组访问功能 测试代码也是如此 C 的
  • 当文件流没有新数据时如何防止fgets阻塞

    我有一个popen 执行的函数tail f sometextfile 只要文件流中有数据显然我就可以通过fgets 现在 如果没有新数据来自尾部 fgets 挂起 我试过ferror and feof 无济于事 我怎样才能确定fgets 当
  • C++ 中的参考文献

    我偶尔会在 StackOverflow 上看到代码 询问一些涉及函数的重载歧义 例如 void foo int param 我的问题是 为什么会出现这种情况 或者更确切地说 你什么时候会有 对参考的参考 这与普通的旧参考有何不同 我从未在现
  • MySQL Connector C/C API - 使用特殊字符进行查询

    我是一个 C 程序 我有一个接受域名参数的函数 void db domains query char name 使用 mysql query 我测试数据库中是否存在域名 如果不是这种情况 我插入新域名 char query 400 spri
  • 类型或命名空间“MyNamespace”不存在等

    我有通常的类型或命名空间名称不存在错误 除了我引用了程序集 using 语句没有显示为不正确 并且我引用的类是公共的 事实上 我在不同的解决方案中引用并使用相同的程序集来执行相同的操作 并且效果很好 顺便说一句 这是VS2010 有人有什么
  • 现代编译器是否优化乘以 1 和 -1

    如果我写 template

随机推荐

  • 通过环境变量告诉 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