помогите произвести и оптимизировать вычисление в динамически создаваемом dll
static double computer(string expression, string x)
{
// компилятор кода C#
ICodeCompiler cs = (new CSharpCodeProvider().CreateCompiler());
// параметры компиляции: DLL в памяти
CompilerParameters cp = new CompilerParameters();
cp.ReferencedAssemblies.Add("system.dll");
cp.GenerateExecutable = false; // создать DLL
cp.GenerateInMemory = true; // создать в памяти
// текст программы на C#:
string code = string.Empty;
code += "using System;\r\n ";
code += "namespace CSEvaluator\r\n";
code += "{ public class Evaluate\r\n";
code += " { public double GetResult()\r\n{double x = " + x + ";\r\n";
code += " return "+ expression +";\r\n }";
code += " private double exp(double x){ return(Math.Exp(x)); }";
code += " private double log(double x){ return(Math.Log(x)); }";
code += " private double log(double x,double s){ return(Math.Log(x,s)); }";
code += " private double pow(double x, double y){ return(Math.Pow(x,y)); }";
code += " private double sin(double x){ return(Math.Sin(x)); }";
code += " private double cos(double x){ return(Math.Cos(x)); }";
code += " private double pi(){ return(Math.PI); }";
code += " }\r\n";
code += "}";
text += code;
// компиляция исходного кода и получение сборки
CompilerResults cr = cs.CompileAssemblyFromSource(cp, code);
if (cr.Errors != null && cr.Errors.Count > 0) // ? ошибки
{
for (int i = 0; i < cr.Errors.Count; i++)
text += "Col {0} - {1}" + cr.Errors.Column + cr.Errors.ErrorText;
return -6666;
}
try // создать объект и вызвать метод для вычисления выражения
{
object ob = cr.CompiledAssembly.CreateInstance("CSEvaluator.Evaluate");
return ((double)ob.GetType().InvokeMember("GetResult", BindingFlags.InvokeMethod, null, ob, new object[] { }));
}
catch (Exception ex) { text += ex.Message; return (0); }
}
Необходимо произвести вычисления минимизации функции. так что данная функция вызывается много раз(например, при методе дихотомии 10 итераций, вызывается 20 раз), а вычисляется минимум функции за 12 секунд. можно ли сократить?
подскажите какая часть кода более трудоемкая.
можно ли создать dll глобально а потом вычислять getresult с параметром string x, передаваемой из texbox и намного ли быстрей будет в таком случае?
на вскидку:
code += "using System;\r\n ";
от этого могут быть проблемы производительности, т.к. каждый раз при изменении объекта типа string происходит создание нового объекта типа string - результата операции, ссылка на который и заносится в code(а тут все радости создания новых объектов - включая как копирование объектов в памяти, так и вызов GC).
используй System.Text.StringBuilder вместо srting.
Необходимо произвести вычисления минимизации функции. так что данная функция вызывается много раз(например, при методе дихотомии 10 итераций, вызывается 20 раз), а вычисляется минимум функции за 12 секунд. можно ли сократить?
И что, 20 раз происходит компиляция (вызов csc.exe)?
Покажите в каком контексте вы используете продемонстрированный код.
+1
В данном случае это ничего не даст вообще.
{
// компилятор кода C#
ICodeCompiler cs = (new CSharpCodeProvider().CreateCompiler());
// параметры компиляции: DLL в памяти
CompilerParameters cp = new CompilerParameters();
cp.ReferencedAssemblies.Add("system.dll");
cp.GenerateExecutable = false; // создать DLL
cp.GenerateInMemory = true; // создать в памяти
// текст программы на C#:
string code = string.Empty;
code += "using System;\r\n ";
code += "namespace CSEvaluator\r\n";
code += "{ public class Evaluate\r\n";
code += " { public double GetResult()\r\n{double x = " + x + ";\r\n";
code += " return "+ expression +";\r\n }";
code += " private double exp(double x){ return(Math.Exp(x)); }";
code += " private double log(double x){ return(Math.Log(x)); }";
code += " private double log(double x,double s){ return(Math.Log(x,s)); }";
code += " private double pow(double x, double y){ return(Math.Pow(x,y)); }";
code += " private double sin(double x){ return(Math.Sin(x)); }";
code += " private double cos(double x){ return(Math.Cos(x)); }";
code += " private double pi(){ return(Math.PI); }";
code += " }\r\n";
code += "}";
text += code;
// компиляция исходного кода и получение сборки
CompilerResults cr = cs.CompileAssemblyFromSource(cp, code);
if (cr.Errors != null && cr.Errors.Count > 0) // ? ошибки
{
for (int i = 0; i < cr.Errors.Count; i++)
text += "Col {0} - {1}" + cr.Errors.Column + cr.Errors.ErrorText;
return -6666;
}
try // создать объект и вызвать метод для вычисления выражения
{
object ob = cr.CompiledAssembly.CreateInstance("CSEvaluator.Evaluate");
return ((double)ob.GetType().InvokeMember("GetResult", BindingFlags.InvokeMethod, null, ob, new object[] { }));
}
catch (Exception ex) { text += ex.Message; return (0); }
}
это функция,
а это вызов из кнопочки:
{
k++;
x1 = (a + b - sgm) / 2;
x2 = (a + b + sgm) / 2;
y1 = computer(expression, convert(x1));
y2 = computer(expression, convert(x2));
if (y1 < y2) { b = x2; } else { a = x1; }
}
просто тогда комп был загружен торентами))
просто тогда комп был загружен торентами))
Т.е. вы "Math.Abs((b - a) / 2) > eps" раз вызываете компиляцию одного и того же выражения? И вы еще спрашиваете, откуда тормоза.
Скомпилируйте выражение один раз и вызывайте его в цикле.
Скомпилируйте выражение один раз и вызывайте его в цикле.
вы что? в данном случае 20 раз вызываю.
выражение не одно и тоже, я просто не знаю как в компилируемый код засунуть переменную из основного кода.
а потом нужен будет метод ньютона и придется 3 разных кода компилить.
а потом нужен будет метод n-го порядка, придется n+1 код собирать...
ну да ладно, попробуем...
только я не знаю где его вписывать... и еще раз: я просто не знаю как в компилируемый код засунуть переменную из основного кода.
подскажите
подскажите
Передайте параметром в конструируемый метод.
можно примерчик
а потом нужен будет метод n-го порядка, придется n+1 код собирать...
Создайте общий интерфейс IEvaluator для всех классов, производящих вычисление и используйте его вместо кода на кнопочке:
{
interface IEvaluator
{
double Evaluate(sometype somevariable);
}
}
{
class NewtonMethod : IEvaluator
{
public double Evaluate(sometype somevariable)
{
....
}
}
}
...
IEvaluator evaluator = new NewtonMethod();
var someresult = evaluator->Evaluate(some_variable);
вы, конечно, меня извините, но при чем тут интерфейс? да, он даст возможность использовать разные методы, но при этом мы будем работать с одной функцией. а нам нужен код, который будет считать рантайм разные функции без парсера, точней используя встроенный разбор шарпа при компиляции кода рантайм.
то есть.. вот можно было написать что то типо
...
double f(double x){return math.sin(x+1)}
Но!!!
нужно такое
которое еще и говорит, мол, типа вы неправильно ввели выражение, ошибка может быть там то.
и без всяких рекурсивных спусков.
я, конечно понимаю, что по хорошему так делать нельзя, но...
можно написать подобное:
button1_click{сборка. вызов от аргумента х}
но как соединить переменную в "string code" и снаружи - в основном коде?
Необходимо произвести вычисления минимизации функции. так что данная функция вызывается много раз(например, при методе дихотомии 10 итераций, вызывается 20 раз), а вычисляется минимум функции за 12 секунд. можно ли сократить?
подскажите какая часть кода более трудоемкая.
Наиболее ресурсоемкая - вызов компилятора CSharp.
Сам работал над этой темой когда-то:
http://sources.codenet.ru/file/3604/MathCompiler_3.2.zip
Если надо могу */.cs прислать. Мыло в личку скиньте.
Могу сказать что сравнительно с трансляцией стеком компиляция оправдана при вызове более 50-500 раз.
вы, конечно, меня извините, но при чем тут интерфейс?
Вам правильный намек дают.