- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我正在尝试通过编写基本代码来学习 CUDA,这有望让我能够更好地将我现有的 C++ 代码转换为 CUDA(用于研究)。
我需要做一些复杂的数字操作,所以我写了这个非常基本的代码来将一个复数数组与一个实数相乘在 GPU 内核中。
#include <complex>
#include <iostream>
#include <cmath>
#include "cuda.h"
#include "math.h"
#include "cuComplex.h"
#define n 5
using namespace std;
#define gpuErrchk(ans) { gpuAssert((ans), __FILE__, __LINE__); }
inline void gpuAssert(cudaError_t code, char *file, int line, bool abort=true)
{
if (code != cudaSuccess)
{
fprintf(stderr,"GPUassert: %s %s %d\n", cudaGetErrorString(code), file, line);
if (abort) exit(code);
}
}
__global__ void func( double *s, cuDoubleComplex *j, cuDoubleComplex *calc ) {
int tid = blockIdx.x;
calc[tid] = cuCmul(j[tid], make_cuDoubleComplex(*s, 0));
}
int main( void ) {
cuDoubleComplex calc[n+1], *dev_j, *dev_calc;
double *dev_s, s[n+1] = { 2.0, 2.0, 2.0, 2.0, 2.0 };
//complex<double> j[n+1]
cuDoubleComplex j[n+1];
for (int i = 1; i <= n; i++) {
j[i] = make_cuDoubleComplex(0, 5);
cout << "\nJ cout = " << cuCreal(j[i]) << ", " << cuCimag(j[i]);
}
// allocate the memory on the GPU
cudaMalloc( (void**)&dev_s, (n+1) * sizeof(double) );
cudaMalloc( (void**)&dev_j, (n+1) * sizeof(double) );
cudaMalloc( (void**)&dev_calc, (n+1) * sizeof(double) );
cudaMemcpy( dev_s, s, (n+1) * sizeof(double), cudaMemcpyHostToDevice );
cudaMemcpy( dev_j, j, (n+1) * sizeof(double), cudaMemcpyHostToDevice );
func<<<n,1>>>( dev_s, dev_j, dev_calc );
//kernel<<<1,1>>>(a_d);
gpuErrchk( cudaPeekAtLastError() );
gpuErrchk( cudaMemcpy(calc, dev_calc, (n+1) * sizeof(double), cudaMemcpyDeviceToHost) );
//cudaMemcpy( calc, dev_calc, (n+1) * sizeof(double), cudaMemcpyDeviceToHost );
for (int i = 1; i <= n; i++) {
cout << "\nCALC cout = " << cuCreal(calc[i]) << ", " << cuCimag(calc[i]);
}
return 0;
}
最后的答案是错误的,我还发现了其他一些我没有得到预期值的地方。
1) 我期望在以下代码行之后为“j”的所有元素生成一个复杂的 double 组 (0, 5i)。但是,我得到的都是 0。这是为什么?
j[i] = make_cuDoubleComplex(0, 5);
2) 为什么我不能使用 cout 打印我的数组?下面显示的代码行给出以下错误:没有运算符“<<”匹配这些操作数。如何在不使用 printf 的情况下解决此问题?
cout << "\nJ = " << j[i];
3) GPU 函数“func”应该给出一个 (0, 10i) 的数组作为最终答案,给出如下随机值:
CALC = -1.#QNAN0
CALC = -1.#QNAN0
CALC = -9255963134931783100000000...000.. etc
CALC = -9255963134931783100000000...000.. etc
4) 对于我的实际研究,复数数组“j”将以 complex(double) 而非 cuDoubleComplex 的格式给出。我可以使用函数“func”对复杂(双)的“j”数组执行类似的操作吗?如果没有,我有什么选择?
我想我已经很好地解释了自己,但请随时提出任何后续问题。C++ 和 CUDA 的新手所以很好 :D
最佳答案
在编写 CUDA 代码时,尤其是当您正在学习或遇到困难时(事情没有按您预期的方式工作),您应该始终这样做 cuda error checking在所有 CUDA API 调用和内核调用上。
我认为您的代码中实际上没有任何 CUDA 功能错误(干得好!),但值得指出。
您的大部分问题是由于您没有正确打印类型 cuDoubleComplex
。您的 printf 语句指定了一个 float
格式参数 (%f
) 但您没有传递一个 float
值(您传递的是一个 cuDoubleComplex
值)。那是行不通的,当您这样做时 printf
会表现得很奇怪,不会给出任何错误指示。
相反,尝试这样的事情:
printf("\nJ = %f, %f", cuCreal(j[i]), cuCimag(j[i]));
这些函数(cuCreal
和 cuCimag
)返回 cuComplex
数的实部和虚部,并将它们作为适当的类型返回, float
或 double
,在这种情况下,从 double
到 float
的隐式转换就可以了执行并可以由 printf
处理(虽然这不是很好的编程习惯——而是使用正确的 printf
格式说明符作为 double
值) .
如果您对两个 printf 语句都进行了更改,我认为您会得到预期的结果——至少我在运行您的代码时做到了。如果您仍然遇到垃圾,那么您的 CUDA GPU 可能无法正常工作,这里是执行我提到的 CUDA 错误检查的地方将帮助您发现问题所在。
关于您关于cout
的问题,答案大致等同于我对printf
的解释。 cout
不理解类型 cuDoubleComplex
,因此会抛出错误。如果您想在不使用 printf
的情况下修复它,请将您的 cuDoubleComplex
转换为其单独的实部和虚部,由 float
或 double 表示
,使用我在上面的 printf
语句中指出的转换函数。
关于您的最后一个问题,将您的 complex
数据转换为 cuDoubleComplex
类型应该不难。根据您在 cuComplex.h
中的实用程序编写一个转换函数来执行此操作。有一些后门方法可以解决这个问题,但它们不是好的编程习惯。
编辑:在回答后续问题时,当前发布的代码中还有两个错误。
dev_j
和 dev_calc
属于 cuDoubleComplex
类型,但您正在执行 cudaMalloc
和 cudaMemcpy
在这些数量上,就好像它们的大小是 double
一样。在下面的代码中,我将那些 sizeof(double)
条目更改为 sizeof(cuDoubleComplex)
。这里是对你的代码的修改,对我有用:
//#include <complex> // not necessary for this code
#include <iostream>
#include <cmath>
//#include "cuda.h" // not necessary when compiling with nvcc
#include "math.h"
#include "cuComplex.h"
#define n 5
using namespace std;
#define gpuErrchk(ans) { gpuAssert((ans), __FILE__, __LINE__); }
inline void gpuAssert(cudaError_t code, char *file, int line, bool abort=true)
{
if (code != cudaSuccess)
{
fprintf(stderr,"GPUassert: %s %s %d\n", cudaGetErrorString(code), file, line);
if (abort) exit(code);
}
}
__global__ void func( double *s, cuDoubleComplex *j, cuDoubleComplex *calc ) {
int tid = blockIdx.x;
calc[tid] = cuCmul(j[tid], make_cuDoubleComplex(*s, 0));
}
int main( void ) {
cuDoubleComplex calc[n+1], *dev_j, *dev_calc;
double *dev_s, s[n] = { 2.0, 2.0, 2.0, 2.0, 2.0 };
//complex<double> j[n+1]
cuDoubleComplex j[n];
for (int i = 0; i < n; i++) {
j[i] = make_cuDoubleComplex(0, 5);
cout << "\nJ cout = " << cuCreal(j[i]) << ", " << cuCimag(j[i]);
}
// allocate the memory on the GPU
cudaMalloc( (void**)&dev_s, (n) * sizeof(double) );
cudaMalloc( (void**)&dev_j, (n) * sizeof(cuDoubleComplex) );
cudaMalloc( (void**)&dev_calc, (n) * sizeof(cuDoubleComplex) );
cudaMemcpy( dev_s, s, (n) * sizeof(double), cudaMemcpyHostToDevice );
cudaMemcpy( dev_j, j, (n) * sizeof(cuDoubleComplex), cudaMemcpyHostToDevice );
func<<<n,1>>>( dev_s, dev_j, dev_calc );
//kernel<<<1,1>>>(a_d);
gpuErrchk( cudaPeekAtLastError() );
gpuErrchk( cudaMemcpy(calc, dev_calc, (n) * sizeof(cuDoubleComplex), cudaMemcpyDeviceToHost) );
//cudaMemcpy( calc, dev_calc, (n+1) * sizeof(double), cudaMemcpyDeviceToHost );
for (int i = 0; i < n; i++) {
cout << "\nCALC cout = " << cuCreal(calc[i]) << ", " << cuCimag(calc[i]);
}
return 0;
}
关于c++ - CUDA - 简单的复数乘法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17476978/
我有一个包含两列的文件,第一列包含纯实数,第二列包含 GNUPLOT 可接受的形式的复数,{a,b}(GNUPLOT 等同于 a + bi)。我想用第二列的绝对值绘制第一列,所以我尝试了这个: 使用
我正在使用 pandas,它可以非常有效地按照我需要的方式对数据进行排序/过滤。 此代码运行良好,直到我将最后一列更改为复数;现在我得到一个错误。 return self._cython_agg_ge
我如何让 Django 意识到 countries 的单数形式是 country 而不是 countrie 最佳答案 来自docs ,如果你有一个名为 num_countries 的模板变量,你可以这
我正在从事一个项目,该项目要求我获取输入、执行 DFT(离散傅立叶变换),然后从这些值中获取过零次数。 我编写了一个算法,但它使用复数,我不知道如何操作/执行计算。这是代码: #include #i
我如何在 C 中动态定义复数的三维数组,以便我可以在访问数组时方便的 [i] [j] [k] 符号中访问? 最佳答案 扩展 Bob__ 的 example将数组分配到堆上而不是堆栈上: #includ
我想在我的 Android 项目中使用复数形式。但是,我提供的值可以是浮点值。 例如,当设置 1.5 星时,我希望这个理解,它不是 1 星而是 1.5 星s。 %d star %d star
问题:这是我的虚数正则表达式: [0-9]{0,}\d\.[0-9]{0,}\d[i]|[0-9]{0,}\d[i] 它只取一个纯复数部分的虚数。 当我的解析器遇到例如String im = "2i"
我知道关键,现在我需要搜索 5000 多个用户数据库时产生的所有 结果。任何用户可能没有一个或多个位置,由 id 和 name 字段标识。因此,我需要一个数组中的结果,不仅仅是第一个/最后一个,而是所
Gidday cobbers/尊敬的同事们, 通过实现卡尔曼预测/校正的多目标跟踪,我在其他 SO 线程中看到建议的一般方法是简单地为每个目标提供一个卡尔曼滤波器 vector/数组。 即'多单目标卡
尽管在 C# naming convention for enum and matching property 上阅读了类似但不完全是我想要的内容,但我还是在问这个问题 我发现我倾向于以复数命名枚举,
我正在尝试使用 getQuantityString基于 Android 开发人员指南检索数量字符串(复数)的资源中的方法 Quantity string (plurals) 我得到的错误是 Error
我想用 C++ 处理复数。因此我包括了#include .现在我的问题是:我如何声明一个变量?(那么我们说的格式是什么:1 + i?) 提前致谢:-) 最佳答案 // 1 + 2i std::com
我有一个名为 agency_persons 的表,其中已有一些数据。我使用 php artisan 创建了一个模型: php artisan make:model AgencyPerson 现在,当我
在 C++ 中,复数 double 的一维数组的最大大小是多少(即 std::complex array[dimension] )? 如果我在 main 和 global 中声明数组,最大大小是否有区
我使用 Mustache 来模板化我的 javascript ajax 调用,这是我的数据和模板: {'joined':1} // ajax responde data json. var myTem
我有这么大的问题。我写了一个关于复数的程序。该程序读取和写入复数,将它们相加等。 他说我应该读一下 Why should I overload a C++ operator as a global f
我将在 java 中重复我必须做的事情,以我认为我需要思考的方式来完成这个任务。 (抱歉,我是编程新手)。 头等舱;为复数定义类。我发现这很容易,我的答案如下。 public class Comple
如何在新的 dev django 版本的管理站点上将某些模型名称从“Categorys”更改为“Categories”?在旧版本中(没有管理站点和管理模型)你可以这样做; http://www.the
我最近才发现一种通过 this video 生成毕达哥拉斯三元组的方法解释它,涉及使用高斯(复杂)整数。到目前为止,我已经设法编写了一个函数,该函数返回由每个高斯整数生成的勾股三元组列表,其中虚部小于
我决定尝试一下 complex.h,然后遇到了一个我认为非常奇怪的问题。 int mandelbrot(long double complex c, int lim) { long doubl
我是一名优秀的程序员,十分优秀!