【问题标题】:C++: Evaluate own mathematical function (function-array like multidimensional analysis) entry-wiseC++:逐项评估自己的数学函数(函数数组,如多维分析)
【发布时间】:2011-05-09 17:37:21
【问题描述】:

你好, 我想评估一个数学函数(用户定义),它在 C++ 中返回一个数组中的几个值(这个函数是一个基于向量的函数 f:R^n->R^m,具有 n 个输入坐标和 m 个输出函数)在 C++ 中参数,例如:

double *my_func(const mxArray *point)
{
    double *dat = mxGetPr(point);
    double *vals = new double[ 3 ];

    vals[0] = dat[0]*dat[0]*dat[0]*dat[0]*dat[0];
    vals[1] = sin(dat[0])*dat[1]*dat[2]*dat[2]*cos(dat[1]);
    vals[2] = exp(dat[0])*sin(dat[0])*dat[3];

    double *pnt = vals; 
    return pnt;
}

目前我在 CPU 上执行此操作。所以我调用了一次函数并返回一个包含所有函数值的数组。因为我现在想在 GPU 上并行化它,所以我考虑了如何去做。

我认为在每个线程中完全评估 my_func() 会有点愚蠢,因为每个线程都会计算整个函数数组。 这是正确的假设吗?

是否有任何方法可以轻松地仅计算函数数组的第 n 个元素并返回它,以便 5 个线程可以轻松地并行计算函数数组,而不是一个 CPU 完全“单独”计算它?

我能想到的唯一方法是:

double my_func0(const mxArray *point)
{
    double *dat = mxGetPr(point);
    return dat[0]*dat[0]*dat[0]*dat[0]*dat[0];
}
double my_func1(const mxArray *point)
{
    double *dat = mxGetPr(point);
    return sin(dat[0])*dat[1]*dat[2]*dat[2]*cos(dat[1]);
}
double my_func2(const mxArray *point)
{
    double *dat = mxGetPr(point);
    return exp(dat[0])*sin(dat[0])*dat[3];
}

etc... 但这对于以后使用该程序的用户来说是相当“不舒服”的,因为如果他想扩展函数数组而不是仅仅适应一个单一的 C++,他总是必须创建新的 C++ 函数-功能。另一个问题是:我必须动态调用函数,因为函数的数量是“动态的”,因此我必须调用 my_func_%%i%% 并且不知道这是否是一个好方法...所以问题是是否有更好的方法来处理这个问题?

【问题讨论】:

    标签: c++ arrays function


    【解决方案1】:

    当您说“user_defined”时,我认为您的意思是其他人写了my_func(),然后您的代码调用了它?

    如果是这种情况,请考虑并行运行多次对my_func() 的调用,而不是尝试分解函数。这意味着编写my_func() 的人只需要编写一个函数,您将负责委派多个调用,确保它们有正确的数据可以处理,并收集结果。

    根据评论更新

    在您的情况下,如果计算vals 的每个成员所需的操作不同,那么用户要么必须通过所需的索引参数化my_func();正如您建议的double my_func(const mxArray *point, const unsigned & index),请注意它现在如何返回单个双精度值,而不是整个结果数组。或者为每个索引提供不同的my_func()double my_func_n(const mxArray *point).

    然后,您可以从任意数量的不同线程调用此函数或一组函数,并获得一个结果以供进一步计算。我们忽略了许多并发问题,但与同时读取/写入数据有关,需要考虑。

    一般多任务处理建议

    在使用 GPU 进行多任务处理之前,请先了解一下 CPU 上的标准多线程处理(我推荐 Boost Thread Libraries 来提供帮助:http://www.boost.org/)。一旦您了解了线程是如何创建和使用的,您可能会更好地了解您可以使用它们做什么以及如何去做。

    如果您将数学函数应用于非常大的矩阵或向量,并且可以使用某些图形函数的硬件实现来获得数学结果,那么使用 GPU 进行多任务处理会变得更加有用。还有更多的库支持 GPGPU(通用 GPU)编程,例如 OpenCL、Nvidia 的 CUDA 或 ATI 的 Stream。看看这些库提供了什么,让您了解它们对您的情况的适用程度。

    【讨论】:

    • 如果我应该把它写到一个函数中,你会怎么做呢?我唯一能想到的(但这看起来很丑)是:double myfunc(double* point, int index) { if(index == 0) return (*point) * (*point) elseif(index == 1) return ... elseif(index == 2) return ...}
    • 您能否扩展一下,向我展示您在主代码中实际使用my_func() 的方式?
    • 好的,目前我这样做:funcValues = my_func(point) 其中 funcValues 是指向 my_func(point) 中动态创建的数组的指针,其中包含单个数学函数的值(如第一个post 而 point 是指向包含要评估的数学坐标的数组的指针)。比我做类似funcValues2 = my_func(point+h) 的事情,然后我通过(funcValues2-funcValues2)/h(伪代码...)计算数值导数。因为funcValues 是一个数组,所以我想并行化它,这样我就可以并行计算所有这些导数
    • 由于每个线程都应该计算一个导数,因此在每个线程中计算funcValues = my_func(point) 是没有用的,因为每个线程只计算一个导数,因此只需要返回的指针数组中的一个元素。这就是为什么我考虑将函数拆分为多个函数,以便 thread1 执行:double derivative1 = (my_func1(coords+h)-my_func1(coords))/h, ... threadN 执行:double derivativeN = (my_funcN(coords+h)-my_funcN(coords))/h
    • 好的,再次感谢。所以你的两个建议都是关于我也建议的东西,我真的很想知道是否没有任何解决方案更“漂亮”(不知道正确的术语来表达代码是丑陋的对立面^^) 和良好的维护。我仍然在考虑两件事:first:当我在 ONE func 中拥有所有内容并使用 switch() 语句(或 if-elseif-elseif...)处理 100 或 200 个案例(对于 100 个或200 个单个函数),这不是条件语句的开销吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多