打印Syms/Matlab功能慢 [英] Printing syms / matlabFunction slow

查看:118
本文介绍了打印Syms/Matlab功能慢的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

尝试使符号替换更快时,我遇到很多麻烦-也就是说,用符号表达式替换变量并获得双精度值.

I am having a lot of trouble trying to make symbolic substitution go faster - that is, substituting in for variables in a symbolic expression and getting out a double.

我正在创建一个复杂的函数f,并计算其jacobian df.这以合理的速度进行,我可以将其保存到文件中.但是,当我尝试使用matlabFunction或什至是disp或fprintf时,系统将挂起并且无法继续进行操作(即使将matlabFunction设置为未优化).这是一个主要问题,因为我需要能够进行合理的快速替换.

I am creating a complicated function f, and calculating its jacobian df. This goes at a reasonable pace, and I can save it to a file just fine. But when I try to use matlabFunction or even disp or fprintf, the system hangs and is unable to proceed further (even when matlabFunction is set to unoptimized). This is a major problem as I need to be able to do reasonably fast substitution.

f向量是24个元素,雅可比行列式是24 x 78(尽管这里仅显示70个变量,所以可以将其压缩到70列;不过我怀疑这是问题所在).

The f vector is 24 elements, and the Jacobian is 24 x 78 (there are only 70 variables that show up here though, so this could be compressed down to 70 columns; I doubt this is the issue though).

我还知道f和df的某些元素很简单,并且在单独访问时可以正常工作,但是f和df的某些更复杂的元素无法显示.我想它们很长,但是由于它们计算得很好,因此无法将它们转换为matlabFunction或显示对我来说没有意义.

I also know that there are certain elements of f and df which are simple and work fine when accessed individually, but certain, more complicated elements of f and df cannot be displayed. I imagine they are very long, but since they are calculated just fine, it doesn't make sense to me that they cannot be transformed into a matlabFunction or displayed.

更奇怪的是,我可以替换所有的符号变量,但是最后完全替换的f向量的最终显示(例如,通过disp),或者转换为double(通过double())似乎要花很长时间.

Even more bizarrely, I can substitute in for all my symbolic variables, but then the final display of the fully substituted f vector (say, via disp), or the conversion to double (through double( )) seems to take forever.

如果您想使用.mat文件,可以在此处进行下载(文件删除器链接,则为288kb).在合理的时间内可以写出该文件怎么办?

If you want to play around with the .mat file, you can get it here (filedropper link, it's 288kb). What can I do to write out this file in a reasonable amount of time?

推荐答案

注意:我从您的评论的角度着眼于这个问题:

Note: I concentrated on the problem from the viewpoint of your comment:

它是矩阵相乘和相加的结果.我曾尝试使用simple命令简化该过程,但是速度非常慢.我曾经成功地将f写入未优化的文件(df没有运气)-花费了2个小时-但是评估它花费了0.8秒,这太慢了.我需要能够在0.02秒内执行评估.

It is the result of a matrix multiplication and addition. I have tried simplifying it along the way, using the simplify command, but that's been incredibly slow. I have succeeded once in writing f to a file unoptimized (no luck for df) - it took 2 hours - but then evaluating it took 0.8 seconds, which is too slow. I need to be able to perform evaluation in about 0.02 seconds.


我开始查看您的f中的元素,直到f(12)为止都很简单.但是,f(13)释放了地狱:


I started looking at the elements in your f, and it was simple up to f(12). However, f(13) unleashed hell:

>> inp.f(13)

ans =

(2289*l4)/100 - (11371197146449238679*l3)/8112963841460668169578900514406400 - (2289*l2)/100 + (11371197146449238679*l5)/8112963841460668169578900514406400 - (2289*l8)/100 - (11371197146449238679*l9)/8112963841460668169578900514406400 + (2289*l10)/100 + (11371197146449238679*l11)/8112963841460668169578900514406400 - (2289*l14)/100 - (11371197146449238679*l15)/8112963841460668169578900514406400 + (2289*l16)/100 + (11371197146449238679*l17)/8112963841460668169578900514406400 - (2289*l20)/100 - (11371197146449238679*l21)/8112963841460668169578900514406400 + (2289*l22)/100 + (11371197146449238679*l23)/8112963841460668169578900514406400 - (2289*l26)/100 - (11371197146449238679*l27)/8112963841460668169578900514406400 + (2289*l28)/100 + (11371197146449238679*l29)/8112963841460668169578900514406400 - (2289*l32)/100 - (11371197146449238679*l33)/8112963841460668169578900514406400 + (2289*l34)/100 + (11371197146449238679*l35)/8112963841460668169578900514406400 - h1*(((cos(x4/2)*cos(x6/2) + sin(x4/2)*sin(x5/2)*sin(x6/2))*(cos(x4/2)*sin(x6/2) - cos(x6/2)*sin(x4/2)*sin(x5/2)) + (sin(x4/2)*sin(x6/2) + cos(x4/2)*cos(x6/2)*sin(x5/2))*(cos(x6/2)*sin(x4/2) - cos(x4/2)*sin(x5/2)*sin(x6/2)) - cos(x5/2)^2*cos(x6/2)*sin(x6/2))*(((x17*(cos(x4/2)*cos(x5/2)*(cos(x6/2)*(cos(x6/2)*sin(x4/2) - cos(x4/2)*sin(x5/2)*sin(x6/2)) + sin(x6/2)*(sin(x4/2)*sin(x6/2) + cos(x4/2)*cos(x6/2)*sin(x5/2))) - cos(x5/2)*sin(x4/2)*(cos(x6/2)*(cos(x4/2)*cos(x6/2) + sin(x4/2)*sin(x5/2)*sin(x6/2)) + sin(x6/2)*(cos(x4/2)*sin(x6/2) - cos(x6/2)*sin(x4/2)*sin(x5/2)))))/2 - (x18*(cos(x4/2)^2*cos(x5/2)^2 + cos(x5/2)^2*sin(x4/2)^2 + sin(x5/2)^2))/2 + (x16*(sin(x5/2)*(cos(x5/2)^2*cos(x6/2)^2 + cos(x5/2)^2*sin(x6/2)^2 + sin(x5/2)^2) + cos(x5/2)*sin(x4/2)*(cos(x5/2)*sin(x4/2)*sin(x5/2) + cos(x5/2)*cos(x6/2)*(cos(x4/2)*sin(x6/2) - cos(x6/2)*sin(x4/2)*sin(x5/2)) - cos(x5/2)*sin(x6/2)*(cos(x4/2)*cos(x6/2) + sin(x4/2)*sin(x5/2)*sin(x6/2))) + cos(x4/2)*cos(x5/2)*(cos(x4/2)*cos(x5/2)*sin(x5/2) - cos(x5/2)*cos(x6/2)*(sin(x4/2)*sin(x6/2) + cos(x4/2)*cos(x6/2)*sin(x5/2)) + cos(x5/2)*sin(x6/2)*(cos(x6/2)*sin(x4/2) - cos(x4/2)*sin(x5/2)*sin(x6/2)))))/2 - (x19*cos(x5/2)*sin(x4/2))/2)*((LEG_MASS*((cos(x7/2)*(sin(x4/2)*sin(x6/2) + cos(x4/2)*cos(x6/2)*sin(x5/2)) + cos(x5/2)*cos(x6/2)*sin(x7/2))*((cos(x4/2)*cos(x6/2) + sin(x4/2)*sin(x5/2)*sin(x6/2))*(x2/2 - BASE_ORIGIN_Z*(cos(x6/2)*sin(x4/2) - cos(x4/2)*sin(x5/2)*sin(x6/2)) - (cos(x4/2)*cos(x6/2) + sin(x4/2)*sin(x5/2)*sin(x6/2))*(BASE_LINK_EXTENTS_Y/2 - BASE_ORIGIN_Y + LEG_LINK_EXTENTS_Y/2) + cos(x5/2)*sin(x6/2)*(BASE_ORIGIN_X - BASE_LINK_EXTENTS_X/4)) - (cos(x4/2)*sin(x6/2) - cos(x6/2)*sin(x4/2)*sin(x5/2))*(x1/2 + BASE_ORIGIN_Z*(sin(x4/2)*sin(x6/2) + cos(x4/2)*cos(x6/2)*sin(x5/2)) + (cos(x4/2)*sin(x6/2) - cos(x6/2)*sin(x4/2)*sin(x5/2))*(BASE_LINK_EXTENTS_Y/2 - BASE_ORIGIN_Y + LEG_LINK_EXTENTS_Y/2) + cos(x5/2)*cos(x6/2)*(BASE_ORIGIN_X - BASE_LINK_EXTENTS_X/4)) + cos(x5/2)*sin(x4/2)*(x3/2 - sin(x5/2)*(BASE_ORIGIN_X - BASE_LINK_EXTENTS_X/4) + BASE_ORIGIN_Z*cos(x4/2)*cos(x5/2) - cos(x5/2)*sin(x4/2)*(BASE_LINK_EXTENTS_Y/2 - BASE_ORIGIN_Y + LEG_LINK_EXTENTS_Y/2))) - (cos(x4/2)*sin(x6/2) - cos(x6/2)*sin(x4/2)*sin(x5/2))*((sin(x5/2)*sin(x7/2) - cos(x4/2)*cos(x5/2)*cos(x7/2))*(x3/2 - sin(x5/2)*(BASE_ORIGIN_X - BASE_LINK_EXTENTS_X/4) + BASE_ORIGIN_Z*cos(x4/2)*cos(x5/2) - cos(x5/2)*sin(x4/2)*(BASE_LINK_EXTENTS_Y/2 - BASE_ORIGIN_Y + LEG_LINK_EXTENTS_Y/2)) - (cos(x7/2)*(sin(x4/2)*sin(x6/2) + cos(x4/2)*cos(x6/2)*sin(x5/2)) + cos(x5/2)*cos(x6/2)*sin(x7/2))*(x1/2 + BASE_ORIGIN_Z*(sin(x4/2)*sin(x6/2) + cos(x4/2)*cos(x6/2)*sin(x5/2)) + (cos(x4/2)*sin(x6/2) - cos(x6/2)*sin(x4/2)*sin(x5/2))*(BASE_LINK_EXTENTS_Y/2 - BASE_ORIGIN_Y + LEG_LINK_EXTENTS_Y/2) + cos(x5/2)*cos(x6/2)*(BASE_ORIGIN_X - BASE_LINK_EXTENTS_X/4)) + (cos(x7/2)*(cos(x6/2)*sin(x4/2) - cos(x4/2)*sin(x5/2)*sin(x6/2)) - cos(x5/2)*sin(x6/2)*sin(x7/2))*(x2/2 - BASE_ORIGIN_Z*(cos(x6/2)*sin(x4/2) - cos(x4/2)*sin(x5/2)*sin(x6/2)) - (cos(x4/2)*cos(x6/2) + sin(x4/2)*sin(x5/2)*sin(x6/2))*(BASE_LINK_EXTENTS_Y/2 - BASE_ORIGIN_Y + LEG_LINK_EXTENTS_Y/2) + cos(x5/2)*sin(x6/2)*(BASE_ORIGIN_X - BASE_LINK_EXTENTS_X/4))))*(sin(x7/2)*(sin(x4/2)*sin(x6/2) + cos(x4/2)*cos(x6/2)*sin(x5/2)) - cos(x5/2)*cos(x6/2)*cos(x7/2)) - LEG_MASS*((sin(x7/2)*(sin(x4/2)*sin(x6/2) + cos(x4/2)*cos(x6/2)*sin(x5/2)) - cos(x5/2)*cos(x6/2)*cos(x7/2))*((cos(x4/2)*cos(x6/2) + sin(x4/2)*sin(x5/2)*sin(x6/2))*(x2/2 - BASE_ORIGIN_Z*(cos(x6/2)*sin(x4/2) - cos(x4/2)*sin(x5/2)*sin(x6/2)) - (cos(x4/2)*cos(x6/2) + sin(x4/2)*sin(x5/2)*sin(x6/2))*(BASE_LINK_EXTENTS_Y/2 - BASE_ORIGIN_Y + LEG_LINK_EXTENTS_Y/2) + cos(x5/2)*sin(x6/2)*(BASE_ORIGIN_X - BASE_LINK_EXTENTS_X/4)) - (cos(x4/2)*sin(x6/2) - cos(x6/2)*sin(x4/2)*sin(x5/2))*(x1/2 + BASE_ORIGIN_Z*(sin(x4/2)*sin(x6/2) + cos(x4/2)*cos(x6/2)*sin(x5/2)) + (cos(x4/2)*sin(x6/2) - cos(x6/2)*sin(x4/2)*sin(x5/2))*(BASE_LINK_EXTENTS_Y/2 - BASE_ORIGIN_Y + LEG_LINK_EXTENTS_Y/2) + cos(x5/2)*cos(x6/2)*(BASE_ORIGIN_X - BASE_LINK_EXTENTS_X/4)) + cos(x5/2)*sin(x4/2)*(x3/2 - sin(x5/2)*(BASE_ORIGIN_X - BASE_LINK_EXTENTS_X/4) + BASE_ORIGIN_Z*cos(x4/2)*cos(x5/2) - cos(x5/2)*sin(x4/2)*(BASE_LINK_EXTENTS_Y/2 - BASE_ORIGIN_Y + LEG_LINK_EXTENTS_Y/2))) + (cos(x4/2)*sin(x6/2) - cos(x6/2)*sin(x4/2)*sin(x5/2))*((cos(x7/2)*sin(x5/2) + cos(x4/2)*cos(x5/2)*sin(x7/2))*(x3/2 - sin(x5/2)*(BASE_ORIGIN_X - BASE_LINK_EXTENTS_X/4) + BASE_ORIGIN_Z*cos(x4/2)*cos(x5/2) - cos(x5/2)*sin(x4/2)*(BASE_LINK_EXTENTS_Y/2 - BASE_ORIGIN_Y + LEG_LINK_EXTENTS_Y/2)) + (sin(x7/2)*(sin(x4/2)*sin(x6/2) + cos(x4/2)*cos(x6/2)*sin(x5/2)) - cos(x5/2)*cos(x6/2)*cos(x7/2))*(x1/2 + BASE_ORIGIN_Z*(sin(x4/2)*sin(x6/2) + cos(x4/2)*cos(x6/2)*sin(x5/2)) + (cos(x4/2)*sin(x6/2) - cos(x6/2)*sin(x4/2)*sin(x5/2))*(BASE_LINK_EXTENTS_Y/2 - BASE_ORIGIN_Y + LEG_LINK_EXTENTS_Y/2) + cos(x5/2)*cos(x6/2)*(BASE_ORIGIN_X - BASE_LINK_EXTENTS_X/4)) - (sin(x7/2)*(cos(x6/2)*sin(x4/2) - cos(x4/2)*sin(x5/2)*sin(x6/2)) + cos(x5/2)*cos(x7/2)*sin(x6/2))*(x2/2 - BASE_ORIGIN_Z*(cos(x6/2)*sin(x4/2) - cos(x4/2)*sin(x5/2)*sin(x6/2)) - (cos(x4/2)*cos(x6/2) + sin(x4/2)*sin(x5/2)*sin(x6/2))*(BASE_LINK_EXTENTS_Y/2 - BASE_ORIGIN_Y + LEG_LINK_EXTENTS_Y/2) + cos(x5/2)*sin(x6/2)*(BASE_ORIGIN_X - BASE_LINK_EXTENTS_X/4))))*(cos(x7/2)*(sin(x4/2)*sin(x6/2) + cos(x4/2)*cos(x6/2)*sin(x5/2)) + cos(x5/2)*cos(x6/2)*sin(x7/2)) + LEG_MASS*(cos(x4/2)*sin(x6/2) - cos(x6/2)*sin(x4/2)*sin(x5/2))*((cos(x7/2)*(sin(x4/2)*sin(x6/2) + cos(x4/2)*cos(x6/2)*sin(x5/2)) + cos(x5/2)*cos(x6/2)*sin(x7/2))*((cos(x7/2)*sin(x5/2) + cos(x4/2)*cos(x5/2)*sin(x7/2))*(x3/2 - sin(x5/2)*(BASE_ORIGIN_X - BASE_LINK_EXTENTS_X/4) + BASE_ORIGIN_Z*cos(x4/2)*cos(x5/2) - cos(x5/2)*sin(x4/2)*(BASE_LINK_EXTENTS_Y/2 - BASE_ORIGIN_Y + LEG_LINK_EXTENTS_Y/2)) + (sin(x7/2)*(sin(x4/2)*sin(x6/2) + cos(x4/2)*cos(x6/2)*sin(x5/2)) - cos(x5/2)*cos(x6/2)*cos(x7/2))*(x1/2 + BASE_ORIGIN_Z*(sin(x4/2)*sin(x6/2) + cos(x4/2)*cos(x6/2)*sin(x5/2)) + (cos(x4/2)*sin(x6/2) - cos(x6/2)*sin(x4/2)*sin(x5/2))*(BASE_LINK_EXTENTS_Y/2 - BASE_ORIGIN_Y + LEG_LINK_EXTENTS_Y/2) + cos(x5/2)*cos(x6/2)*(BASE_ORIGIN_X - BASE_LINK_EXTENTS_X/4)) - (sin(x7/2)*(cos(x6/2)*sin(x4/2) - cos(x4/2)*sin(x5/2)*sin(x6/2)) + cos(x5/2)*cos(x7/2)*sin(x6/2))*(x2/2 - BASE_ORIGIN_Z*(cos(x6/2)*sin(x4/2) - cos(x4/2)*sin(x5/2)*sin(x6/2)) - (cos(x4/2)*cos(x6/2) + sin(x4/2)*sin(x5/2)*sin(x6/2))*(BASE_LINK_EXTENTS_Y/2 - BASE_ORIGIN_Y + LEG_LINK_EXTENTS_Y/2) + [...] ... Output truncated.  Text exceeds maximum line length of 25,000 characters for Command Window display.

(实际输出被截断以适合SO的30k个字符限制,但您可以达成协议)

(actual output truncated to fit in 30k character limit of SO, but you get the deal)

我押注matlabFunction的解析器不适合这种规模的输入.那里也有一些奇怪的事情:例如8e33顺序的整数字符串文字.

I'd wager the parser of matlabFunction was not meant for inputs of this magnitude. There are also some weird things in there: like integer string literals on the order of 8e33.

因此,我仔细研究了您的功能.幸运的是,您可以将函数转换为字符串,然后对它们进行处理,这只会占用大量CPU时间,而不会占用内存.

So I took a closer look at your function. Fortunately you can convert your functions to strings, and work on those, which is only heavy on CPU time but not on memory.

Preproc:

for k=1:24
   fstring2{k}=char(inp.f(k));
end

函数长度:

>> cellfun(@length,fstring2)

ans =

  Columns 1 through 12

          11          11          11          11          11          11          11          11          11          11          11          11

  Columns 13 through 24

     2301006     2300241     2299996     8425640     8416273     8424306     1375443     1305245     1302440     1237876     1381084     1310884

休斯顿,我们遇到了问题.

这些大量的符号函数野兽破坏了matlabFunction的解析器,或者更可能的是,您在操作期间耗尽了内存.当我尝试simplify f(13)时,我确定确实在几秒钟内丢失了8 GB的更好的一半.

These massive beasts of symbolic functions break the parser of matlabFunction, or what's more probable, you run out of memory during the operation. I sure did when I tried to simplify f(13), lost the better half of 8 GB within seconds.

仅作为概念验证,我试图模拟函数中涉及的计算工作.我检查了f(13)(第一只野兽).有关所涉及操作的一些信息:

Just as a proof-of-concept I tried to mock the computational effort involved in your functions. I inspected f(13) (the first beast). Some info about the operations involved:

>> length(strfind(char(inp.f(13)),'*'))

ans =

      134710

>> length(strfind(char(inp.f(13)),'+'))

ans =

       36932

>> length(strfind(char(inp.f(13)),'-'))

ans =

       26855

>> length(strfind(char(inp.f(13)),'/'))

ans =

      183380

>> length(strfind(char(inp.f(13)),'ln'))

ans =

     0

>> length(strfind(char(inp.f(13)),'exp'))

ans =

     0

>> length(strfind(char(inp.f(13)),'cos'))

ans =

       78700

>> length(strfind(char(inp.f(13)),'sin'))

ans =

       84142

我试图计时一个模拟运算,该运算涉及类似数量的操作:

I tried to time a mock computation involving a similar number of operations:

x=zeros(36000,1);
tic;
for k=1:36000
   x(k)=(((sin(sin(((cos(cos(3.1+2.1)*3.1)*6.1)*5.1)*9.1)/4.1)/3.1)/6.1)/5.1)/8.1;
end
toc;

Elapsed time is 0.010895 seconds.

这分别涉及36000个加法,144000个乘法,180000个除法和对sincos72000调用.

This involves 36000 additions, 144000 multiplications, 180000 divisions and 72000 calls to sin and cos, each.

现在,如果我们假设这是一个正确的数字,并且假设您的函数具有类似的操作分布,那么您正在查看的函数的40080434个字符,即17个等效的f(13)单位.这表明即使您可以转换为适当的matlab函数,您的运行时仅调用f(而且我们完全没有查看df)至少需要0.1-0.2的时间秒.

Now, if we assume that this is a correct ballpark figure, and if we assume that your functions have a similar distribution of operations, then you're looking at 40080434 characters of functions, which is 17 equivalent f(13) units. This suggests that even if you could convert to a proper matlab function, your runtime to just calling f (and we haven't looked at df at all) would take at least 0.1-0.2 seconds.

由于问题的性质,我不确定是否有解决方法.我可能会尝试在python中使用sympy进行相同的操作,在那里您还可以转换为lambda(相当于匿名函数的python等效项)以用于数值计算.如果那个成功,那么至少您可以尽快使用您的函数.

Due to the nature of your problem, I'm not sure there's a way around it. I would probably try doing the same using sympy in python, there you can also convert to a lambda (the python equivalent of an anonymous function) for use in numerical computations. If that would succeed, then at least you could use your functions as quickly as possible.

发布我不太乐观的答案后,我相信我已经成功地将您的函数转换为匿名函数.它很脏,但似乎可以正常工作.

After posting my less optimistic answer, I believe I've succeeded in converting your function to an anonymous one. It's dirty, but it seems to work.

首先将函数转换为上述字符串,然后使用symvar提取变量名.然后使用这些函数名称创建一个函数定义.不幸的是,我只能使用eval对其进行破解. 应该是一种更优雅的方法,但是无论如何,我们都对可实现的运行时感兴趣.

First you convert your function to a string as above, then use symvar to extract the variable names. Then you create a function definition using these function names; unfortunately I could only hack it up using eval. There should be a more elegant way, but anyway we're interested in the achievable runtimes.

varcell=symvar(fstring2{13}); %variables of inp.f(13)
vars2=strcat(varcell,','); %add a comma to each var
vars3=[vars2{:}]; %put them into a single string
vars3=vars3(1:end-1); %remove trailing comma

f13=eval(['@(' v3 ') ' fstring2{13}]); %this is your numeric function

转换很麻烦,但是匿名函数的实际构造很快,并且在内存上不太难.虚拟运行时:

The conversion is nasty, but the actual construction of the anonymous function is quick and not too hard on memory. Dummy runtime:

>> tic; ftry(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58), toc

ans =

   1.1417e+06

Elapsed time is 0.069252 seconds.

例如,通过允许函数中的数组操作或将所有58个输入作为单个数组输入传递,可以使其变得更加用户友好.但是您的运行时将是相同的.这只是一个功能,大约有17个功能.您可能永远都无法获得想要的提速.

It could be made much more user-friendly, for instance by allowing array operations in the function, or passing all 58 inputs as a single array input. But yor runtime will be the same. And this is just one function, and you have roughly 17 of these. You might never get the speed-up you're hoping for.

(无论如何,我确实开始学习

(And anyway, I did start getting

线程"AWT-EventQueue-0"中的异常java.lang.OutOfMemoryError:Java堆空间

Exception in thread "AWT-EventQueue-0" java.lang.OutOfMemoryError: Java heap space

在整个磨难之后出现错误,因此其成功也可能取决于您对成功"的定义;)

errors after this whole ordeal, so its success might also depend on your definition of "success";)

这篇关于打印Syms/Matlab功能慢的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆