2014 dxdy logo

Научный форум dxdy

Математика, Физика, Computer Science, Machine Learning, LaTeX, Механика и Техника, Химия,
Биология и Медицина, Экономика и Финансовая Математика, Гуманитарные науки




На страницу 1, 2  След.
 
 Maple 9 и DLL на Visual С++ 2005 Express Edition
Сообщение22.11.2015, 08:51 
Имеется Maple 9 в 32-x разрядной среде Windows XP. Он всем хорош для символьных вычислений. Но медленный в некоторых очень простых действиях. А именно при поиске значения в очень большом двухуровневом дереве (список из списков целых чисел). Само дерево можно сформировать в Maple и выгрузить в файл. Это однократное действие. А вот поиск по нему требуется выполнять в цикле с максимально возможной эффективностью. Хочу организовать такой поиск это при помощи внешней процедуры DLL. Установил Visual С++ 2005 Express Edition и MASM 8.0, как дополнение к нему. Предполагаю, что одна внешняя процедура в DLL будет резервировать память и загружать дерево поиска из файла. Вторая должна осуществлять сам поиск. Её желательно написать на ассемблере. Проблема в том, что у меня совсем нет опыта работы с C++ и написания DLL в нём. С ассемблером работал, но очень давно, в эпоху DOS с 16-ти разрядными регистрами сегментов CS, DS, ES, SS и 16-ти разрядным адресным пространством внутри сегментов. В связи с этим хочу прояснить несколько вопросов.

1. Правильно ли я выбрал средства для решения поставленной задачи? Или имеется другое решение, более оптимальное по скорости вычислений. Maple исключить не могу, поскольку кроме поиска по дереву в цикле требуется выполнять факторизацию полинома.

2. Достаточно ли Visual С++ 2005 Express Edition и MASM 8.0 для написания DLL библиотеки для Maple 9.

3. Можно ли сделать так, что после вызова первой процедуры в DLL загруженный ею массив данных и сама библиотека DLL останутся в памяти и будут доступны при вызовах второй процедуры в цикле из Maple.

4. Буду очень признателен, если подскажете, как пошагово настроить Visual С++ 2005 Express Edition и MASM 8.0 для решения изложенной выше задачи и как должен выглядеть начальный фрагмент кода - подключение WIN API и прочие необходимые заголовки.

 
 
 
 Re: Maple 9 и DLL на Visual С++ 2005 Express Edition
Сообщение22.11.2015, 10:42 
А если попробовать написать "поиск значения в очень большом двухуровневом дереве (список из списков целых чисел)" на самом Maple ? Там же есть встроенный паскалеобразный язык. Процедуру можно оформить в виде библиотеки (точнее пакета), и потом вызывать ее аналогично стандартной через with мойпакет и пр.
Возможно, скорость будет лучше, так как, наверно, Maple рассматривает кучу случаев с разными деревьями, а вы неявно подразумеваете какой-то один шаблон деревов.

 
 
 
 Re: Maple 9 и DLL на Visual С++ 2005 Express Edition
Сообщение22.11.2015, 17:41 
Я только вещественную арифметику в СКА Maple использовал (с целочисленной не разбирался). Пока знатоки целочисленной арифметики не пришли, я частично отвечу.

В разных версиях имеются существенные различия. Для 9-ой легко нагуглить в сети руководство (я с 9-ой версией вообще не работал) в котором есть нужный раздел:
Maple 9 Advanced Programming Guide: 6.2 External Calling: Using Compiled Code in Maple
(Это на тот случай, если справки не хватает.)

1. Грубо говоря, возможно два варианта.
Первый: типы аргументов и возвращаемого значения достаточно просты (нет необходимости создания интерфейсной DLL). Пользовательскую DLL можно писать на чём угодно, лишь бы тип вызова был «стандартный С».

Второй: типы более сложные и требуется специальная интерфейсная функция (для преобразования переменных), помещаемая в DLL (Wrapper). В этом случае Maple вызывает интерфейсную функцию, а затем интерфейсная функция вызывает функцию Вашей библиотеки. Для автоматической генерации этой функции (запуска компилятора для создания этой DLL-обертки) разработчиками рекомендуется MS VC. [При установке бывают баги, поэтому для автоматической генерации интерфейсной функции необходимо самому изменить директории или внести изменения в настройки Maple.]

Если говорить о скорости вычислений (напомню, что с целочисленными вещами я не работал). Будете писать asm-функции или asm-блоки, то всё будет определяться не компилятором, а знанием «современного ассемблера».

2. Не знаю. Обычно пишут консольное и dll. Когда заработает, тестят в Maple. После этого функции вставляют в консольное и оптимизируют (без всякой DLL). После, опять переносят функции из консольного в dll и тестят вызова в Maple. Что ещё тут может понадобиться?

3. Да, можно.

4. Обычно в руководствах по Maple рассматривают в качестве примера сложение двух целых чисел. И в качестве примера создания DLL на C по сути то же:
Пошаговое руководство. Создание и использование библиотеки DLL (C++).
[В общем, я бы быстро накатал простое консольное и dll, и после проверил вызова функций dll из Maple, а уже затем писал в теме конкретные затруднения. А то воскресенье закончится и наступит рабочая неделя. И, очень может быть, ждать ответа придётся 6 дней. :)]

По сути темы: Maple глючный и медленный на многих задачах. Я бы, по возможности, попробовал рассмотреть другие варианты. Будем надеяться, эти варианты Вам подскажут.

 
 
 
 Re: Maple 9 и DLL на Visual С++ 2005 Express Edition
Сообщение23.11.2015, 10:01 
Ruslan_Sharipov в сообщении #1075613 писал(а):
Вторая должна осуществлять сам поиск. Её желательно написать на ассемблере.


Не нужно. Ассемблер давно вытеснен из вычислительных задач. Не потому что никого не интересует скорость, а потому что нужна веская специфика чтобы получить преимущество в скорости от его использования. У вас я таковой не вижу. Ассемблер смело отбрасывайте. Нормальные компиляторы С++ генерирует весьма машинноэффективный код, как правило эффективнее попыток новичков ускорить что-то путём переписывания на ассемблере.

Так что учите С++.

 
 
 
 Re: Maple 9 и DLL на Visual С++ 2005 Express Edition
Сообщение25.11.2015, 00:56 
GAA в сообщении #1075716 писал(а):
Пользовательскую DLL можно писать на чём угодно, лишь бы тип вызова был «стандартный С».
Заврался. stdcall — это не «стандартный C». Под win32 в С тип вызова по умолчанию — cdelc. В общем, как и написано в документации, надо указывать тип вызова как __stdcall.
У меня в простых случаях даже в Delphi работает. Но сильно не разбирался, поэтому только в простых случаях.
Вот исходный текст библиотеки
код: [ скачать ] [ спрятать ]
Используется синтаксис Delphi
library Tst;

function mul(x, y: Double): Double; stdcall;
begin
 Result:= x*y;
end;

function IPower(Base: Double; Exponent: Integer): Double; stdcall;
var i: integer;
begin
 Result:= 1; for i:=Exponent downto 1 do Result:= Result*Base;
end;

function imul(a: longint; b: longint): longint; stdcall;
begin
 Result:= a*b;
end;

exports mul, IPower, imul;
end.
И текст Classic Worksheet Maple 15
Код:
> dmul:= define_external('mul', x::float[8], y::float[8], RETURN::float[8], LIB="Tst.dll"):
> ip  := define_external('IPower', x::float[8], y::integer[4], RETURN::float[8], LIB="Tst.dll"):
> imul:= define_external('imul', x::integer[4], y::integer[4], RETURN::integer[4], LIB="Tst.dll"):
> dmul(2, 3);
                               6.
> ip(2.0, 3);
                               8.
> ip(-3.0, 3);
                             -27.
> imul(2, 6);
                              12
> imul(-2, 4);
                              -8
Как будто все правильно. И в Maple 7 работает. Скорее всего, и в Maple 9 работать будет.

 
 
 
 Re: Maple 9 и DLL на Visual С++ 2005 Express Edition
Сообщение25.11.2015, 05:09 
GAA в сообщении #1075716 писал(а):
В качестве примера создания DLL на C по сути то же: Пошаговое руководство. Создание и использование библиотеки DLL (C++).
Спасибо. С этим разобрался. Подробный отчёт здесь. Дальнейшие Ваши рекомендации тоже буду использовать.
GAA в сообщении #1075716 писал(а):
По сути темы: Maple глючный и медленный на многих задачах.
Я к нему очень привык. Менять трудно.

 
 
 
 Re: Maple 9 и DLL на Visual С++ 2005 Express Edition
Сообщение25.11.2015, 15:11 
Ruslan_Sharipov в сообщении #1076470 писал(а):
Подробный отчёт здесь.


Чтобы не было проблем при линковке с мэплами и прочим не надо заключать функции в классы и неймспейсы, а надо заключать их объявления в extern "C" { }.
Ну это уже в примерам из мэпла можно увидеть.

 
 
 
 Re: Maple 9 и DLL на Visual С++ 2005 Express Edition
Сообщение25.11.2015, 15:12 
Ruslan_Sharipov в сообщении #1075613 писал(а):
4. Буду очень признателен, если подскажете,... как должен выглядеть начальный фрагмент кода.
Вот простой пример библиотеки с примитивной функцией
Используется синтаксис C++
 // mult.h
extern "C" __declspec(dllexport)  int __stdcall mult(int a, int b);

Используется синтаксис C++
 // Mult.cpp : Defines the exported functions for the DLL application.
#include "stdafx.h"
#include "mult.h"

 int __stdcall mult(int a, int b)
{
        return (a*b);
}

Содержание dllmain.cpp не менял.
Classic Worksheet Maple 12
Код:
> My_mult:=define_external('mult','a'::(integer[4]),'b'::(integer[4]),RETURN::(integer[4]),LIB="mult.dll"):
> My_mult(2,-3);
                                     -6

Компилировал в Visual C++ 2008 Express Edition (2005 нет под рукой). Если в Classic Worksheet Maple 12 работает, то и в Maple 9, скорее всего, будет работать.

Опишите Ваши функции, тогда можно будет подумать о более осмысленном примере.

-- Ср 25.11.2015 14:13:51 --

aa_dav, да. Опоздал я, но пусть будет :)

 
 
 
 Re: Maple 9 и DLL на Visual С++ 2005 Express Edition
Сообщение25.11.2015, 21:34 
GAA в сообщении #1076597 писал(а):
Опишите Ваши функции, тогда можно будет подумать о более осмысленном примере.
Я говорил о функциях из Вашего начального сообщения: резервирования памяти + загрузки данных из файла (или другим способом) и функции поиска. В частности хотелось бы следующих уточнений:
1. Какова длина в байтах максимально длинного числа (4, 8, 16?)
2. Какова структура списка списков? Нельзя ли считать, что имеется просто массив указателей на массивы, содержащие целые числа?
3. В чем состоит условие поиска в списке списков? [Опять же, длина данных, в частности, если в условие входят целые числа, то какова их длина в байтах?]
4. Что должна возвращать функция поиска? Номер списка и номер элемента в этом списке?

 
 
 
 Re: Maple 9 и DLL на Visual С++ 2005 Express Edition
Сообщение27.11.2015, 03:46 
GAA в сообщении #1076725 писал(а):
1. Какова длина в байтах максимально длинного числа (4, 8, 16?)
Пусть это будет 16. Первый список - это список простых чисел $r$ в диапазоне от $2$ до $r_{\max}\leqslant 2^{16}-1$.
GAA в сообщении #1076725 писал(а):
2. Какова структура списка списков? Нельзя ли считать, что имеется просто массив указателей на массивы, содержащие целые числа?
Для каждого $r$ и для каждого $p=0,...,r-1$ создан список из не более чем $r$ чисел $q$ в диапазоне $0\leqslant q\leqslant r-1$.
GAA в сообщении #1076725 писал(а):
3. В чем состоит условие поиска в списке списков?
4. Что должна возвращать функция поиска?
На входе функция поиска получает два больших числа $p$ и $q$ в формате Maple Unlimited Integer. В цикле по простым числам $r$ из списка числа $p$ и $q$ обрубаются по модулю $r$ и проверяется наличие числа $q$ в списке с номером $p$. Как только наличие обнаружено, поиск прекращается и возвращается $true$. Если ни в одном из списков ни для одного простого $r$ обнаружений нет - возвращается $false$.

Списки готовятся заранее и могут быть организованы в оперативной памяти любым возможным способом с целью достижения максимальной быстроты поиска. Число $r_{\max}$ подбирается из условия, чтобы поиск по спискам был менее затратным по времени, чем прямая проверка разрешимости в целых числах $t$ полиномиального диофантового уравнения высокой степени $f(p,q,t)=0$ в заданном диапазоне сканирования по большим целым числам $p$ и $q$.

 
 
 
 Re: Maple 9 и DLL на Visual С++ 2005 Express Edition
Сообщение27.11.2015, 06:08 
Ruslan_Sharipov в сообщении #1077227 писал(а):
GAA в сообщении #1076725 писал(а):
1. Какова длина в байтах максимально длинного числа (4, 8, 16?)
Пусть это будет 16.
16 — это байт или бит? [Из дальнейшего текста складывается впечатление, что бит.] Если число байт меньше 8, то это не принципиально, а если больше 8 (больше 64 бит), то начинаются трудности.

 
 
 
 Re: Maple 9 и DLL на Visual С++ 2005 Express Edition
Сообщение27.11.2015, 08:54 
Шестнадцать бит разумеется. Большими будут только входные числа $p$ и $q$. Но они затем обрубаются по модулю $r$. Для того, чтобы не заморачиваться с обработкой больших чисел в формате Maple Unlimited Integer, можно цикл по $r$ cделать в самом Maple, а функцию поиска вызывать с тремя аргументами $r$, $p$, $q$, которые будут целыми в смысле C++ с битностью, определяемой разрядностью процессора. Сканирование лучше всего проводить цепочечными командами ассемблера типа repe scasw. Здесь битность понижается до 16.

 
 
 
 Re: Maple 9 и DLL на Visual С++ 2005 Express Edition
Сообщение27.11.2015, 18:27 
Понятно. Спасибо.
Если передавать в dll 16-битные целые, то проблем не возникает. Не возникает проблем и с возвращением логического результата. Проверял в Maple 12-ой версии, слегка переделав предыдущий пример
Используется синтаксис C++
// mult.h
extern "C" __declspec(dllexport) bool __stdcall search(__int16 p, __int16 q, __int16 r);
extern "C" __declspec(dllexport) __int8 __stdcall ReadData(void);
Используется синтаксис C++
// Mult.cpp : Defines the exported functions for the DLL application.
#include "stdafx.h"
#include "mult.h"

__int8 __stdcall ReadData(void)
{// Возвращает ошибку чтения данных. Пока заглушка
        return 0;
}
bool __stdcall search(__int16 p, __int16 q, __int16 r)
{  
    return p == q;
}

Код:
> My_searh:=define_external('search','p'::(integer[2]),'q'::(integer[2]), 'r'::(integer[2]), RETURN::boolean[1], LIB="mult.dll"):
> ReadData:=define_external('ReadData', RETURN::integer[1], LIB="mult.dll"):
> x := ReadData();
> if x <> 0 then print("error", x); end if;
x:= 0
> My_searh(1, 1, 1), My_searh(1, 2, 1);
true, false

Добавить по существу мне нечего.

На всякий случай отмечу, что при помощи условной компиляции (#ifdef) можно сделать один h-файл и для создания консольного приложения, и для создания dll (причем отдельно dll для Maple, и dll для консольного). Для этого использовать определение xxx_Export (xxx — имя проекта) из списка Preprocessor Definitions и задавать еще одно, например Maple, чтобы различать для чего компилируем (Maple / консольное). [В среде можно посмотреть «определения» в диалоговом окне свойств проекта. Открыть это окно можно при помощи “Alt +F7” или из соответствующего элемента раздела Project главного меню. Это все в 2008. В 2005 может по-другому, не проверял.]

Да, masm, видимо, не понадобится. Можно будет обойтись __asm блоками. Удобней.

[Редактирование: заменил «понадобиться» на «понадобится».]

 
 
 
 Re: Maple 9 и DLL на Visual С++ 2005 Express Edition
Сообщение02.12.2015, 18:30 
GAA, спасибо! С Вашей помощью всё получилось. Скорость многократно возросла. Но её всё ещё не хватает. Буду постепенно переносить в С++ большую часть вычислений, выполняемых в основном цикле, и менять алгоритм, если потребуется.

 
 
 
 Re: Maple 9 и DLL на Visual С++ 2005 Express Edition
Сообщение05.12.2015, 22:41 
Хочу немного продолжить тему. Следуя подсказкам в Интернете, я научился создавать таймерную функцию, которая работает в параллельной нити процесса (thread) запускаемой из DLL. При этом основная нить процесса может производить быстрые вычисления в блоке __asm, лишь проверяя в цикле значение флага, сигнализирующего о необходимости прервать вычисления. Возможно, мой опыт может пригодиться, поэтому спешу им здесь поделиться.

Сначала в Visual С++ 2005 Express Edition через меню File > New > Project создаём пустой проект (Visual C++ emptyproj) с именем Multithread_Timer_DLL и указываем Multithread_Timer_solution в качестве имени решения (solution name). В свойствах созданного проекта выбираем опции

Configuration Type = Dynamic Library (.dll)
Common Language Runtime support = Common Language Runtime Support (/clr)

Затем к проекту добавляем два файла Multithread_Timer_DLL.h и Multithread_Timer_DLL.cpp со следующим содержимым
Используется синтаксис C++
// Multithread_Timer_DLL.h
extern "C" __declspec(dllexport)  void __stdcall Set_Time_Period(int Time_Period);
extern "C" __declspec(dllexport)  int __stdcall Get_Time_Period();
extern "C" __declspec(dllexport)  char __stdcall Is_Ready_to_Stop();

код: [ скачать ] [ спрятать ]
Используется синтаксис C++
// Multithread_Timer_DLL.cpp: Defines exported functions for the DLL application.
//
#include "Multithread_Timer_DLL.h"
#include <process.h>
#include <stdlib.h>
int     Time_Period_Local;
char Ready_to_Stop=0;
void Run_Timer_Thread(void * arg)
{
 _sleep(Time_Period_Local);
 Ready_to_Stop=1;
}
void __stdcall Set_Time_Period(int Time_Period)
{
 Time_Period_Local=Time_Period;
 Ready_to_Stop=0;
 _beginthread(Run_Timer_Thread,0,(void*)12);
}
int __stdcall Get_Time_Period()
{
 return(Time_Period_Local);
}
char __stdcall Is_Ready_to_Stop()
{
 return(Ready_to_Stop);
}

После этого надо выбрать ещё одну опцию, хотя у меня она выставляется автоматически. В свойства проекта а разделе Configuration Properrties > C/C++ > Code Generation надо выбрать

Runtime Library = Multi-threaded Debug DLL (/MDd)

В Maple 9 прописываем три внешние процедуры следуя рекомендациям GAA:
Код:
> Set_Time_Period:=define_external('Set_Time_Period', 'Time_Period'::(integer[4]), LIB="C:/Documents and Settings/User/My Documents/Visual Studio 2005/Projects/Multithread_Timer_solution/debug/Multithread_Timer_DLL.dll"):

Код:
> Get_Time_Period:=define_external('Get_Time_Period', RETURN::(integer[4]),LIB="C:/Documents and Settings/User/My Documents/Visual Studio 2005/Projects/Multithread_Timer_solution/debug/Multithread_Timer_DLL.dll"):

Код:
> Is_Ready_to_Stop:=define_external('Is_Ready_to_Stop',RETURN::(boolean[1]), LIB="C:/Documents and Settings/User/My Documents/Visual Studio 2005/Projects/Multithread_Timer_solution/debug/Multithread_Timer_DLL.dll"):

Здесть User - это имя пользователя, с которым Вы входите в Windows. Дальнейший код должен продемонстрировать работоспособность внешних процедур с заданием временной задержки в 40 секунд
Код:
> a:=1:
> Start_time:=time():
> Set_Time_Period(40000):
> Get_Time_Period();
> for i while not(Is_Ready_to_Stop()) do
>  a:=a+1:
> end do:
> print(time()-Start_time):
> print(a):

 
 
 [ Сообщений: 18 ]  На страницу 1, 2  След.


Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group