Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/matlab/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
尽可能高效地使用约60000个短符号表达式计算向量(Matlab,C)_C_Matlab_Benchmarking_Mex - Fatal编程技术网

尽可能高效地使用约60000个短符号表达式计算向量(Matlab,C)

尽可能高效地使用约60000个短符号表达式计算向量(Matlab,C),c,matlab,benchmarking,mex,C,Matlab,Benchmarking,Mex,我有一个大约60000个短符号表达式的符号向量,每个单元格一个。 此类表达式通常如下所示: (81*A_1_1*W1)/(646*L)-(81*A_6_6*L)/(646*W1) 这些表达式中总共出现了大约20个不同的变量,我知道其中的值 问题的中心是尽可能有效地评估这个符号矩阵。我将来需要做1000次(这个计算是优化问题中目标函数的一部分) 我编写了一个Matlab函数,如下所示: function [K_1_uniques]=K_1_computation(C1,W1,L) %Define

我有一个大约60000个短符号表达式的符号向量,每个单元格一个。 此类表达式通常如下所示:

(81*A_1_1*W1)/(646*L)-(81*A_6_6*L)/(646*W1)

这些表达式中总共出现了大约20个不同的变量,我知道其中的值

问题的中心是尽可能有效地评估这个符号矩阵。我将来需要做1000次(这个计算是优化问题中目标函数的一部分)

我编写了一个Matlab函数,如下所示:

function [K_1_uniques]=K_1_computation(C1,W1,L)

%Define variables from elasticity tensor C1
A_1_1=C1(1,1);
A_1_2=C1(1,2);
A_1_6=C1(1,3);
A_2_2=C1(2,2);
A_2_6=C1(2,3);
A_6_6=C1(3,3);
D_1_1=C1(4,4);
D_1_2=C1(4,5);
D_1_6=C1(4,6);
D_2_2=C1(5,5);
D_2_6=C1(5,6);
D_6_6=C1(6,6);
A_4_4=C1(7,7);
A_4_5=C1(7,8);
A_5_5=C1(8,8);

%Initialize vector
K_1_uniques=zeros(65251,1);

%Populate vector
K_1_uniques(1)=(81*A_1_1*W1)/(646*L) - (81*A_6_6*L)/(646*W1);
K_1_uniques(2)=(63*A_4_5*L)/1427660 - (27*A_5_5*W1)/1427660;
K_1_uniques(3)=(63*A_4_4*L)/1427660 - (27*A_4_5*W1)/1427660;
...
K_1_uniques(65251)=- (2187*A_4_4*L)/62817040 - (2187*A_4_5*W1)/102077690;
第一次运行MATLAB大约需要12.3秒(使用tic-toc计时),随后运行需要0.030158秒,因为我猜它保留了编译?我是否正确地假设Mex预编译将消除这种长时间的首次运行(IMO由于JIT)

因此,我想知道是否可以通过将其作为Mex文件运行来进一步加快计算速度?我没有编码器软件包,所以我不得不手工编写c代码(好吧,至少语法是这样,我显然会使用Matlab的fprintf来编写65000个表达式)

这是我第一次编写cmex代码(我有一些基本的C经验)。我已经设法运行了一个“hello world”和一些基本的整数和双精度算术,所以我对正在发生的事情有了一个想法

如果我理解正确,Mex文件是预编译的C代码,因此与Matlab中的JIT编译相比应该节省一些时间

我想在Mex文件中输入一个8*8的双矩阵(弹性张量C1)以及两个双值(标量),W1和L

然后程序应该分配一个_1_1=C1(1,1),一个_1_2=C1(1,2)。。。就像在Matlab代码中一样。然后,它应该填充一个新的矩阵数组,该数组有65521个输出项

下面我有一个这样的代码的简单概要(仅5个条目),语法并不完全正确,但这只是一个开始。它编译时没有错误,但如果我试图运行它,它会崩溃。我将A_1_1和A_1_2指定为标量输入,因为我不确定如何从输入矩阵C1中提取它们。我也不知道如何写入matrixArray,所以我使用了cellArray(这应该更改)

如果您能帮助运行此代码,我们将不胜感激。另外,我不知道任何关于内存分配等的C技巧可以进一步加速这个过程。对于这方面的任何建议或评论,以及我在更广泛意义上的尝试,我将不胜感激。

我倾向于信任。即使是接受答案的人也认为答案是正确的。你可以再读一遍

代码显然可以从中受益的一件事是。这表明Matlab的JIT不执行此操作,尽管未指明Matlab的版本。对于您的代码来说,这将需要大量繁琐的工作


当您使用符号数学工具箱时,该函数可能会对此有所帮助。我不确定这会有多好,因为即使是在内存充足的快速机器上,符号工具箱也会因大量输入而陷入困境,因此您可能需要解决这个问题。当然,只要你小心,查找和替换也可以使用。使用后一种方法,您可以首先查找并消除小的公共子表达式,然后将它们组合起来。Matlab的编辑器在处理大文件时遇到问题,因为它试图对其着色,并在每次发生更改时检查代码,因此您也可以切换到功能齐全的文本编辑器,该编辑器具有高级搜索和替换功能。只要使用标准优化级别编译,迁移到mex还应该消除许多常见的子表达式。但在这一点上,将其作为更多的标准循环进行移植将更有意义。

您能否更清楚地理解“符号向量”和“符号表达式”的含义?这些只是字符串,您正在以双精度进行计算。或者你们是在执行实际的符号数学,从符号变量中得到精确的答案。如果不是后者,那么我会避免将其称为“象征性”以避免混淆。由于您甚至还没有优化您的Matlab代码,您不应该担心C代码:预成熟优化。另外,第一次运行的时间过长也可能是由于内存分配或糟糕的编码。我假设
K_1_uniques
有许多非常相似的行块。尝试矢量化这些。在Matlab中,这个对象的类是“符号的”,它们是使用Matlab的符号引擎muPad操作的符号数学表达式。我假设您是在符号数学工具箱初始化之后计时的?即使是在新发布的Matlab上运行
symsx
也需要几秒钟,因为整个
sym
类都需要实例化,而且它很大。如果所有变量都是class
sym
,那么我认为像这样预先分配可能更有意义:
K_1_uniques=sym(零(65251,1);)
。否则,您的输出甚至不是符号性的(如果任何输入都是符号变量而不是符号值,那么您应该会得到一个错误)。如果我能请您不要将您的回答建立在我前面的问题上,那么问题是不同的。你说了很多关于我的代码没有被优化的事情——这和我前面的问题中的代码不同。与此同时,它已经非常精简。让我示范一下;这里的65000行实际上是500*500矩阵中的唯一值。我很想听听您认为我可以如何进一步优化我在这里发布的几段代码?我想你会很难回答。@Kobye:我的答案基于你为这个问题发布的代码片段,可以用来优化它,除非你的65000多行代码中没有一个公共子表达式。现在,我澄清了这些都是法案
#include "mex.h" /* Always include this */
void mexFunction(double nlhs, mxArray *plhs[], /* Output variables */
                double nrhs, mxArray *prhs[]) /* Input variables */
{
#define N 5
double A_1_1=*mxGetPr(prhs[0]);
double A_6_6=*mxGetPr(prhs[1]);

plhs[0]=mxCreateCellArray(1, N);
mxSetCell(plhs[0], 1, 2*A_1_1/84 + 3*A_6_6/92);
mxSetCell(plhs[0], 2, 5*A_1_1/120 + 7*A_6_6/11);
mxSetCell(plhs[0], 3, 2*A_1_1/56 + 4*A_6_6/82);
mxSetCell(plhs[0], 4, 12*A_1_1/7 + 3*A_6_6/48);
mxSetCell(plhs[0], 5, 2*A_1_1/74 + 8*A_6_6/92);

return;
}