2014 dxdy logo

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

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




Начать новую тему Ответить на тему На страницу 1, 2  След.
 
 Maple 9 и DLL на Visual С++ 2005 Express Edition
Сообщение22.11.2015, 08:51 


12/05/07
566
г. Уфа
Имеется 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 


15/11/15
916
А если попробовать написать "поиск значения в очень большом двухуровневом дереве (список из списков целых чисел)" на самом Maple ? Там же есть встроенный паскалеобразный язык. Процедуру можно оформить в виде библиотеки (точнее пакета), и потом вызывать ее аналогично стандартной через with мойпакет и пр.
Возможно, скорость будет лучше, так как, наверно, Maple рассматривает кучу случаев с разными деревьями, а вы неявно подразумеваете какой-то один шаблон деревов.

 Профиль  
                  
 
 Re: Maple 9 и DLL на Visual С++ 2005 Express Edition
Сообщение22.11.2015, 17:41 
Заслуженный участник


12/07/07
4438
Я только вещественную арифметику в СКА 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 


11/12/14
893
Ruslan_Sharipov в сообщении #1075613 писал(а):
Вторая должна осуществлять сам поиск. Её желательно написать на ассемблере.


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

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

 Профиль  
                  
 
 Re: Maple 9 и DLL на Visual С++ 2005 Express Edition
Сообщение25.11.2015, 00:56 
Заслуженный участник


12/07/07
4438
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 


12/05/07
566
г. Уфа
GAA в сообщении #1075716 писал(а):
В качестве примера создания DLL на C по сути то же: Пошаговое руководство. Создание и использование библиотеки DLL (C++).
Спасибо. С этим разобрался. Подробный отчёт здесь. Дальнейшие Ваши рекомендации тоже буду использовать.
GAA в сообщении #1075716 писал(а):
По сути темы: Maple глючный и медленный на многих задачах.
Я к нему очень привык. Менять трудно.

 Профиль  
                  
 
 Re: Maple 9 и DLL на Visual С++ 2005 Express Edition
Сообщение25.11.2015, 15:11 


11/12/14
893
Ruslan_Sharipov в сообщении #1076470 писал(а):
Подробный отчёт здесь.


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

 Профиль  
                  
 
 Re: Maple 9 и DLL на Visual С++ 2005 Express Edition
Сообщение25.11.2015, 15:12 
Заслуженный участник


12/07/07
4438
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 
Заслуженный участник


12/07/07
4438
GAA в сообщении #1076597 писал(а):
Опишите Ваши функции, тогда можно будет подумать о более осмысленном примере.
Я говорил о функциях из Вашего начального сообщения: резервирования памяти + загрузки данных из файла (или другим способом) и функции поиска. В частности хотелось бы следующих уточнений:
1. Какова длина в байтах максимально длинного числа (4, 8, 16?)
2. Какова структура списка списков? Нельзя ли считать, что имеется просто массив указателей на массивы, содержащие целые числа?
3. В чем состоит условие поиска в списке списков? [Опять же, длина данных, в частности, если в условие входят целые числа, то какова их длина в байтах?]
4. Что должна возвращать функция поиска? Номер списка и номер элемента в этом списке?

 Профиль  
                  
 
 Re: Maple 9 и DLL на Visual С++ 2005 Express Edition
Сообщение27.11.2015, 03:46 


12/05/07
566
г. Уфа
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 
Заслуженный участник


12/07/07
4438
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 


12/05/07
566
г. Уфа
Шестнадцать бит разумеется. Большими будут только входные числа $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 
Заслуженный участник


12/07/07
4438
Понятно. Спасибо.
Если передавать в 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 


12/05/07
566
г. Уфа
GAA, спасибо! С Вашей помощью всё получилось. Скорость многократно возросла. Но её всё ещё не хватает. Буду постепенно переносить в С++ большую часть вычислений, выполняемых в основном цикле, и менять алгоритм, если потребуется.

 Профиль  
                  
 
 Re: Maple 9 и DLL на Visual С++ 2005 Express Edition
Сообщение05.12.2015, 22:41 


12/05/07
566
г. Уфа
Хочу немного продолжить тему. Следуя подсказкам в Интернете, я научился создавать таймерную функцию, которая работает в параллельной нити процесса (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  След.

Модераторы: Karan, Toucan, PAV, maxal, Супермодераторы



Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group