大数据的情况下如何高效的计算表达式的值

xingqiliudehuanghun 2009-10-26 11:35:26
加精
最近的一个项目需要进行蒙特卡洛模拟,并且需要对模拟结果进行表达式求职计算
计算的公式不固定一般的格式是这样$0+$1*2/$3*2.5且随着业务的复杂还需要
进行多次迭代计算。数据量很大最少的也要进行2-3万次计算。

我试了用自己写的表达式求职程序和Mozilla的Rhino效率上都不是很理想,可能是自己
水平比较差,用Mozilla的Rhino居然比自己写的程序快一倍。我们用的jdk1.5所以不能
用jdk1.6中才支持的编译后执行脚本的方法。

想过尝试动态生成Java文件然后编译执行,但是一想起在服务器环境这个程序可能需要
同时计算多个表达式......越想越觉得不可靠.

大家处理这样的问题有什么好的思路,请给些指点.
...全文
2529 90 打赏 收藏 举报
写回复
用AI写文章
90 条回复
切换为时间正序
请发表友善的回复…
发表回复
Rover_Humanity 2012-02-19
  • 打赏
  • 举报
回复
真心不懂。。。
hellolck123 2011-12-14
  • 打赏
  • 举报
回复
看别人帖子的感觉——我就像一张白纸
junon 2010-04-10
  • 打赏
  • 举报
回复
此贴就如2年前刚上CSND,看别人帖子的感觉——我就像一张白纸
阿_布 2009-11-11
  • 打赏
  • 举报
回复
mark!
xmilier 2009-11-05
  • 打赏
  • 举报
回复
好东西 长见识了 可惜都不会 stdlib stdio 不应该是c的库吗?
  • 打赏
  • 举报
回复
非常感谢Forcal,都结贴了还这样热心的提供帮助。我们的那个项目利用Janino动态编译已经可以初步解决
我们的问题了。谢谢你提供的信息,我会把他推荐给我的搞c++的同学。因为一直做java Web开发,关注c++
很少,看了下相关的介绍,那个库确实是个好东西。可惜我们用不上,一是因为我们的项目还没有复杂到那个
程序,自己写个动态编译的Java程序足以应付了,再有就是我们的团队里没有人熟悉如何用JNI调用c++,而且
那个库是需要依赖Windows的,这一点也不能不考虑。
Hawk2099 2009-11-03
  • 打赏
  • 举报
回复
才2-3万次计算啊?我有个项目一般需要计算200百万(Mega)次表达式的值,头疼啊!有谁有好的解决办法?我的项目是用VC++。
forcal 2009-11-03
  • 打赏
  • 举报
回复
上面例子VC的代码如下:

	cout<<"VC++     正对表达式进行循环求和计算,请等待... ..."<<endl;
z=0.0; old=clock();
for(x=0.0;x<=1.0;x=x+0.0011)
for(y=1.0;y<=2.0;y=y+0.0011)
{
z=z+cos(1.0-sin(1.2*pow(x+0.1,y/2.0-x)+cos(1.0-sin(1.2*pow(x+0.2,y/3.0-x))))-cos(1.0-sin(1.2*pow(x+0.3,y/4.0-x)))-cos(1.0-sin(1.2*pow(x+0.4,y/5.0-x)+cos(1.0-sin(1.2*pow(x+0.5,y/6.0-x))))-cos(1.0-sin(1.2*pow(x+0.6,y/7.0-x)))));
}
now=clock();
cout<<"VC++ 计算结果:"<<setprecision(20)<<z<<' ';
cout<<" 运行时间:"<<now-old<<" 即: "<<(double)(now-old)/CLOCKS_PER_SEC<<"秒"<<endl<<endl;

forcal 2009-11-03
  • 打赏
  • 举报
回复
可以回复的。大家看Forcal能否满足要求,需要你的项目能加载dll。
Forcal一级函数的计算速度约为(C/C++)或FORTRAN速度的50%左右,二级函数的速度稍有降低。

FORCAL与VC的速度比较:

表达式:(x,y)=cos{1-sin[1.2*[x+0.1]^(y/2-x)+cos{1-sin[1.2*[x+0.2]^(y/3-x)]}]-cos
{1-sin[1.2*[x+0.3]^(y/4-x)]}-cos{1-sin[1.2*[x+0.4]^(y/5-x)+cos{1-sin[1.2*[x+0.5]
^(y/6-x)]}]-cos{1-sin[1.2*[x+0.6]^(y/7-x)]}}}

FORCAL正对表达式进行循环求和计算,请等待... ...
forcal计算结果:19160.536601703152 运行时间:1782 即: 1.782秒

VC++ 正对表达式进行循环求和计算,请等待... ...
VC++ 计算结果:19160.536601703152 运行时间:1328 即: 1.3280000000000001秒

我的blog:http://blog.csdn.net/forcal
forcal 2009-11-03
  • 打赏
  • 举报
回复
结贴了,还能回复吗?
pf_ma 2009-11-03
  • 打赏
  • 举报
回复
楼上几位说的都听不懂,:(

俺的苯办法:方法类似于8楼

(公式动态解析没有做)
代码在VC下编译执行通过了
执行时间上,函数DynCalc2()是编死的代码的10 - 15倍左右
我怀疑switch语句上浪费了不少条件判断的时间,对汇编不了解,如果能直接jump (*pOpt)到各自的处理中,因该还能提高一些性能

废话不说了,上代码


#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <tchar.h>

//==============================================================================
//
// Define Operator
//

#define DATA_1 0x81 // Push Data 1
#define DATA_2 0x82 // Push Data 2
#define DATA_3 0x83 // Push Data 3
#define DATA_4 0x84 // Push Data 4
#define DATA_5 0x85 // Push Data 5
#define DATA_6 0x86 // Push Data 6
#define DATA_7 0x87 // Push Data 7
#define DATA_8 0x88 // Push Data 8

#define OPT_ADD 0x01 // + (Pop 2 Data, Push Result)
#define OPT_SUB 0x02 // - (Pop 2 Data, Push Result)
#define OPT_MUL 0x03 // * (Pop 2 Data, Push Result)
#define OPT_DIV 0x04 // / (Pop 2 Data, Push Result)

#define OPT_DUP 0x11 // Dup Data (Pop 1 Data, Push 2 Copy)
#define OPT_SWAP 0x12 // Swap Data (Pop 2 Data, Swap Data, Push 2 Data)

#define OPT_END 0xFF // Pop 1 Data, Return

//==============================================================================
//
// Function
//

__forceinline DOUBLE WINAPI DynCalc(BYTE * pOpt, DOUBLE * pData)
{
DOUBLE dStack[1024] = { 0 };
DOUBLE * pStack = dStack;

DOUBLE dTemp;

for (;;)
{
switch (*pOpt)
{
case DATA_1: *pStack = pData[0]; pStack++; break;
case DATA_2: *pStack = pData[1]; pStack++; break;
case DATA_3: *pStack = pData[2]; pStack++; break;
case DATA_4: *pStack = pData[3]; pStack++; break;
case DATA_5: *pStack = pData[4]; pStack++; break;
case DATA_6: *pStack = pData[5]; pStack++; break;
case DATA_7: *pStack = pData[6]; pStack++; break;
case DATA_8: *pStack = pData[7]; pStack++; break;

case OPT_ADD: pStack--; *(pStack - 1) += *pStack; break;
case OPT_SUB: pStack--; *(pStack - 1) -= *pStack; break;
case OPT_MUL: pStack--; *(pStack - 1) *= *pStack; break;
case OPT_DIV: pStack--; *(pStack - 1) /= *pStack; break;

case OPT_DUP:
{
*pStack = *(pStack - 1);
pStack ++;
break;
}
case OPT_SWAP:
{
dTemp = *(pStack - 1);
*(pStack - 1) = *(pStack - 2);
*(pStack - 2) = dTemp;
break;
}
case OPT_END:
return *(pStack - 1);
}

pOpt++;
}
}


VOID WINAPI DynCalc2(DWORD dwLoop, BYTE * pOpt, DOUBLE * pData, DOUBLE * pResult)
{
DOUBLE dStack[1024] = { 0 };
DOUBLE * pStack = dStack;
BYTE * pRawOpt = pOpt;

DOUBLE dTemp;

for (;;)
{
switch (*pOpt)
{
case DATA_1: *pStack = pData[0]; pStack++; break;
case DATA_2: *pStack = pData[1]; pStack++; break;
case DATA_3: *pStack = pData[2]; pStack++; break;
case DATA_4: *pStack = pData[3]; pStack++; break;
case DATA_5: *pStack = pData[4]; pStack++; break;
case DATA_6: *pStack = pData[5]; pStack++; break;
case DATA_7: *pStack = pData[6]; pStack++; break;
case DATA_8: *pStack = pData[7]; pStack++; break;

case OPT_ADD: pStack--; *(pStack - 1) += *pStack; break;
case OPT_SUB: pStack--; *(pStack - 1) -= *pStack; break;
case OPT_MUL: pStack--; *(pStack - 1) *= *pStack; break;
case OPT_DIV: pStack--; *(pStack - 1) /= *pStack; break;

case OPT_DUP:
{
*pStack = *(pStack - 1);
pStack ++;
break;
}
case OPT_SWAP:
{
dTemp = *(pStack - 1);
*(pStack - 1) = *(pStack - 2);
*(pStack - 2) = dTemp;
break;
}
case OPT_END:
{
*pResult = *(pStack - 1);

pResult ++;
pStack --;

pOpt = pRawOpt;
dwLoop --;

if (dwLoop == 0)
return;

continue;
}
}

pOpt++;
}
}

int main()
{
DOUBLE dP1 = (DOUBLE)rand() / 600.0;
DOUBLE dP2 = (DOUBLE)rand() / 601.0;
DOUBLE dP3 = (DOUBLE)rand() / 602.0;
DOUBLE dP4 = (DOUBLE)rand() / 603.0;
DOUBLE dResult;

DWORD dwLoop = 1000000;

BYTE btOpt[] = {DATA_1, DATA_2, DATA_3, OPT_MUL, DATA_4, OPT_DIV, DATA_5, OPT_MUL, OPT_ADD, OPT_END};
DOUBLE dData[] = {dP1, dP2, 2.0, dP3, 2.5};

DOUBLE * pData2 = (DOUBLE *)malloc(dwLoop * sizeof(dData));
DOUBLE * pResult = (DOUBLE *)malloc(dwLoop * sizeof(dResult));

DWORD s, e;
DWORD i;

{
DOUBLE * pTemp = pData2;

for (i = 0; i < dwLoop; i++)
{
memcpy(pTemp, dData, sizeof(dData));
pTemp += (sizeof(dData) / sizeof(DOUBLE));
}
}


//==============================================================================

// s = GetTickCount();
//
// for (i = 0; i < dwLoop; i++)
// {
// dResult = DynCalc(btOpt, dData);
// }
//
// e = GetTickCount();
// printf("%f, %d\n", dResult, e - s);

//==============================================================================

s = GetTickCount();

DynCalc2(dwLoop, btOpt, pData2, pResult);

e = GetTickCount();
printf("%f, %d\n", *pResult, e - s);

//==============================================================================

s = GetTickCount();

for (i = 0; i < dwLoop; i++)
{
dResult = dP1 + dP2 * 2.0 / dP3 * 2.5;
}

e = GetTickCount();
printf("%f, %d\n", dResult, e - s);

//==============================================================================

return 0;
}






  • 打赏
  • 举报
回复
200百万,这么大的计算量。无论怎么优化单机完成恐怕也不会理想到哪去吧,应该应该考虑多机并发计算了。
Riching_Chang 2009-11-02
  • 打赏
  • 举报
回复
提高速度考虑 并发实现撒
csucbh 2009-11-02
  • 打赏
  • 举报
回复
学习 不错了
Ramanda 2009-11-01
  • 打赏
  • 举报
回复
看看。不知道怎么弄
sky9323 2009-11-01
  • 打赏
  • 举报
回复
很好呀
sky9323 2009-11-01
  • 打赏
  • 举报
回复
都是这样的
flyinghawl 2009-11-01
  • 打赏
  • 举报
回复
看不懂啊
fengxingyang 2009-11-01
  • 打赏
  • 举报
回复
好东西 谢谢
ffwyb 2009-10-31
  • 打赏
  • 举报
回复
好多强人啊,学习到了!
加载更多回复(66)

62,620

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧