powered by simpleCommunicator - 2.0.59     © 2025 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / C++ [игнор отключен] [закрыт для гостей] / C++ BigIntegers parallel library
25 сообщений из 104, страница 3 из 5
C++ BigIntegers parallel library
    #38391545
SerVal
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
в ядрах GPU в обход шины PCI-EBandwidth памяти RAM-GPU = 100-300 GByte/sec, а PCI-E gen2 16x = 8 GBytes/sec. Вы уверены, что RAM-GPU у вас слабое звено?
Или у вас данные в ядрах GPU окажутся в обход шины PCI-E? ;)
Для AMD Fusion или Intel HD Graphics - копирования массивов не будет:
http://social.msdn.microsoft.com/Forums/vstudio/en-US/6426345c-9110-4e58-9f18-a6320b5f75ad/amp-and-zero-copy .
...
Рейтинг: 0 / 0
C++ BigIntegers parallel library
    #38391644
m_Sla
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SerValm_SlaНа cpu в одном потоке.... Exec time : 0.037000 seconds.
Поздравляю! ... как известно,быстрее всего работает код, которого о5 же никто не видел. :)
Код: plaintext
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.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
#include <iostream>
#include <vector>
#include <string>

#include <stdio.h>      /* printf */
#include <time.h>       /* clock_t, clock, CLOCKS_PER_SEC */

using namespace std;

//=======================================================================
class BigInt
{
public:
    BigInt() { };

    void print();
    void fromString(const std::string& str);
    void add(BigInt& num);

    size_t getLength() const
    {
        return number.size();
    }

    enum Sign { negative = -1, zero = 0, positive = 1 };
private:
    Sign sign;
    vector<char> number;
};
//=======================================================================
void BigInt::print()
{
    cout<<endl<<"num size="<<number.size()<<endl<<"num=";
    for (int i=number.size()-1; i>=0; i--)
    {
        cout<< (char)(number[i]+'0');
    }
    cout<<endl;
}
//=======================================================================
void BigInt::fromString(const std::string& str)
{
    int str_size= str.size();
    number.reserve(str_size+1);

    for (int i = str_size-1; i>=0; i--)
    {
        number.push_back(str[i]-'0');
    }
}
//=======================================================================
void BigInt::add(BigInt& summand)
{
    vector<char> rez;
    vector<char> *summand1;
    if(number.size() > summand.number.size())
    {
        rez=number;
        summand1=&summand.number;
    }
    else
    {
        rez=summand.number;
        summand1=&number;
    }

    for(size_t i=0, imax=summand1->size()-1; i<=imax; i++)
    {
        rez[i]+=summand1->at(i);

        if(rez[i]>9) //carry?
        {
            rez[i]-=10;

            if(i==imax)
            {
                rez.push_back(1);
            }
            else
            {
                rez[i+1]++;
            }
        }
    }

    number=rez;
}
//=======================================================================
int main()
{
    BigInt n1,n2;
    string num1,num2;

    clock_t t;

    t = clock();

    const size_t NUMBER_OF_DIGITS=10000000;

    num1.reserve(NUMBER_OF_DIGITS*10);
    num2.reserve(NUMBER_OF_DIGITS*10);
    for(size_t i=0; i<NUMBER_OF_DIGITS; i++)
    {
        //num1+="9999999999";
        num1+="1234567123";
        num2+="7654321765";
    }
    t = clock() - t;
    printf ("==================\nConstruct 2 strings \nExec time : %f seconds.\n==================\n",((float)t)/CLOCKS_PER_SEC);

    t = clock();
    n1.fromString(num1);
    n2.fromString(num2);
    t = clock() - t;
    printf ("Construct 2 numbers \nExec time : %f seconds.\n==================\n",((float)t)/CLOCKS_PER_SEC);

    if(n1.getLength()>1000)
    {
        cout<<"n1.size="<<n1.getLength()<<endl;
        cout<<"n2.size="<<n2.getLength()<<endl;
    }
    else
    {
        n1.print();
        n2.print();
    }

    t = clock();
    n1.add(n2);
    t = clock() - t;
    printf ("CPU: A = add(B,C)\nExec time : %f seconds.\n==================\n",((float)t)/CLOCKS_PER_SEC);

    if(n1.getLength()<=1000) n1.print();

    cout<<"add.size="<<n1.getLength()<<endl;

    return 0;
}

SerValОднако ж не совсем понятно, что Вы хотели сказать. Что одно ядро работает быстрее нескольких?
У Вас сложение на CPU по быстродействию примерно равно сложению на GPU. При этом сложение на CPU можно еще оптимизировать, например SSE прикрутить. Какой смысл в GPU и многопоточности?
...
Рейтинг: 0 / 0
C++ BigIntegers parallel library
    #38391651
m_Sla
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вот результаты с использованием gmp 5.1.2
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
==================
Construct 2 strings
Exec time : 0.039000 seconds.
==================
str1 size=10000000
str2 size=10000000
Construct 2 numbers
Exec time : 4.361000 seconds.
==================
CPU: A = add(B,C)
Exec time : 0.003000 seconds.
==================

Process returned 0 (0x0)   execution time : 4.427 s
Press any key to continue.

Код: plaintext
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.
#include <iostream>
#include <stdio.h>
#include "gmp.h"
#include <string>
#include <stdio.h>      /* printf */
#include <time.h>       /* clock_t, clock, CLOCKS_PER_SEC */


using namespace std;

int main ()
{
    string num1,num2;

    clock_t t;

    t = clock();

    const size_t NUMBER_OF_DIGITS=1000000;

    num1.reserve(NUMBER_OF_DIGITS*10);
    num2.reserve(NUMBER_OF_DIGITS*10);
    for(size_t i=0; i<NUMBER_OF_DIGITS; i++)
    {
        //num1+="9999999999";
        num1+="1234567123";
        num2+="7654321765";
    }
    t = clock() - t;
    printf ("==================\nConstruct 2 strings \nExec time : %f seconds.\n==================\n",((float)t)/CLOCKS_PER_SEC);
    cout<<"str1 size="<<num1.size()<<endl;
    cout<<"str2 size="<<num2.size()<<endl;


    mpz_t n1, n2, sum;
    mpz_init2 (n1,40*NUMBER_OF_DIGITS);
    mpz_init2 (n2,40*NUMBER_OF_DIGITS);
    mpz_init2 (sum,40*NUMBER_OF_DIGITS);

    t = clock();
    mpz_set_str(n1,num1.c_str(),10);
    mpz_set_str(n2,num2.c_str(),10);
    t = clock() - t;
    printf ("Construct 2 numbers \nExec time : %f seconds.\n==================\n",((float)t)/CLOCKS_PER_SEC);

    t = clock();
    mpz_add(sum,n1,n2);
    t = clock() - t;
    printf ("CPU: A = add(B,C)\nExec time : %f seconds.\n==================\n",((float)t)/CLOCKS_PER_SEC);
    //cout<<"Sum is "; mpz_out_str (stdout, 10, sum); cout<<endl;

    mpz_clear (n1);
    mpz_clear (n2);
    mpz_clear (sum);

    return 0;
}

...
Рейтинг: 0 / 0
C++ BigIntegers parallel library
    #38392275
SerVal
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Добрый день, m_Sla .

Про n1.add(n2) - какое ж это сложение?
Это не "А= В+С", а реализация оператора "+=". -> A += B
- теряется одно из слагаемых - оно становится результатом.
...это как говорят в Одессе - две большие разницы. :)
У меня числа складаваются и результат присваивается третьему числу:
Код: plaintext
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.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
#include <amp.h>
#include <iostream>
#include <chrono>
#include "BigInt.h"

using namespace std;
using namespace chrono;
using namespace concurrency;

//*******************
// Выбор сопроцессора по подстроке в описании напр: "NVIDIA", "ATI", "INTEL"
// если сопроцессор найден - он устанавливается как сопроцессор по-умолчанию.
// если не найден, сопроцессором остаётся тот, что в системе по-умолчанию(тот, что выводит изображение на экран)
bool pick_accelerator(std::wstring vendor_name)
{
	accelerator accs;
	std::wstring description= accs.get_description();
	bool b_result = description.find((std::wstring)vendor_name) != std::string::npos;
	if(b_result) return true;

	std::vector<accelerator> accs_list = accelerator::get_all();
    //accelerator chosen_one;

	for(int i=0; i<accs_list.size(); i++)
	{
		accs=(accelerator)accs_list[i];
		std::wstring acc_description = accs.get_description();

		bool exists= acc_description.find(vendor_name) != std::string::npos;
		if(exists) { accelerator::set_default((accs.device_path)); return true;}
	}

	return false;
}
//*******************
void print_duration(high_resolution_clock::time_point t1, high_resolution_clock::time_point t2)
{
	std::chrono::duration<double> time_span = duration_cast<duration<double>>(t2 - t1);
	std::cout.precision(3);
	std::cout << "Exec time : " << time_span.count() << " seconds.";	std::cout << std::endl;
}

//********************************
//********************************

int main( int argc, char *argv[])
{
	setlocale(LC_CTYPE, "russian");
   	string opt="-default";
	if(argc>1) 	opt = argv[1];
	
	//**** выбор сопроцессора ****
	bool b_result=true;
	if(opt =="-nvidia")
	{
		b_result= pick_accelerator(L"NVIDIA");
		if(b_result==false)
		{std::printf("Accelerator nVIDIA not found.\n"); return 0;}
	}

	if((opt == "-ati") || (opt == "-amd"))
	{
		b_result= pick_accelerator(L"ATI");
		if(b_result==false)
		{std::printf("Accelerator AMD not found.\n"); return 0;}
	}

	if(opt == "-intel")
	{
		b_result= pick_accelerator(L"INTEL");
		if(b_result==false)
		{std::printf("Accelerator Intel not found.\n"); return 0;}
	}
	//**** конец выбора сопроцессора *****
	
	std::chrono::high_resolution_clock::time_point t1, t2;

	accelerator default_accelerator;
	std::wcout << L"Accelerator : " << default_accelerator.description<< std::endl;
	std::printf("==================\n");

	std::cout << "Строки для BigInt1 и BigInt2."<< endl;
   
   string string1;
   string string2;
 
   for(size_t i=0; i<10000000; i++)
   {
	   string1 += "7654321765";
	   string2 += "1234567123";
   }
 
   std::cout << "строка1 : "<< string1.size() << " цифр." << endl;
   std::cout << "строка2 : "<< string2.size() << " цифр." << endl;
   std::cout << "Конструируем 2 числа:"<< endl;

   t1 = std::chrono::high_resolution_clock::now();

   BigInt BigInt1(string1);
   BigInt BigInt2(string2);
   BigInt BigInt3;

   t2 = std::chrono::high_resolution_clock::now();
   print_duration(t1,t2); // время затраченное конструктором на 2 числа.
	/*
  cout << "BigInt1 = " << BigInt1 << endl;
  cout << "BigInt2 = " << BigInt2 << endl;
	*/
  //************ Начало теста ****************
   std::printf("==================\n");

   std::cout << "CPU: A = add(B,C) "<< endl;
   t1 = std::chrono::high_resolution_clock::now();
   
   BigInt3 = add(BigInt1, BigInt2);

   t2 = std::chrono::high_resolution_clock::now();
   //cout << "Длина результата : "<< BigInt3.getLength() <<endl;
   //cout << "A + B = " << BigInt3 << endl;
   print_duration(t1,t2); // CPU: время затраченное на сложение

   std::printf("==================\n");
   std::cout << "GPU: A = add_gpu(B,C)"<< endl;
   t1 = std::chrono::high_resolution_clock::now();

   BigInt3 = add_gpu(BigInt1, BigInt2);

   t2 = std::chrono::high_resolution_clock::now();
   //cout << "Длина результата : "<< BigInt3.getLength() <<endl; 
   //std::cout << "A + B = " << BigInt3 << endl;
   print_duration(t1,t2); // GPU:время затраченное на сложение
	std::printf("==================\n");
  //************ Конец теста ****************
	
	return 0;
}

про gmp 5.1.2
==================
CPU: A = add(B,C)
Exec time : 0.003000 seconds.
==================
Теряется ли в gmp 5.1.2 одно из слагаемых - не знаю.
Однако, охотно верю.
******
То что последовательное сложение у меня сделано криворуко - согласен.
Можно переписать получше. И оптимизировать его можно. Только зачем?
Как Вы показали, всё оптимизировано до нас в доступных библиотеках.
m_SlaКакой смысл в GPU и многопоточности? Похоже, уже на числах в 100 миллионами цифр, параллельное сложение обгоняет сложение на одном ядре.
Вот:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
D:\aProjects\TestBigInt\x64\Debug>TestBigInt.exe -ati
Accelerator : ATI Radeon HD 5800 Series
==================
Строки для BigInt1 и BigInt2.
строка1 : 100000000 цифр.
строка2 : 100000000 цифр.
Конструируем 2 числа:
Exec time : 7.85 seconds.
==================
CPU: A = add(B,C)
Exec time : 17 seconds.
==================
GPU: A = add_gpu(B,C)
Exec time : 14.5 seconds.
==================

*Тем не менее, сделаю сложение на CPU векторами, или попробую прикрутить gmp 5.1.2(для сравнения).
Всем привет и хорошего настроения. :)
...
Рейтинг: 0 / 0
C++ BigIntegers parallel library
    #38392381
?
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
?
Гость
SerValGuestSerVal, а переносы между разрядами при сложении вы что вообще не учитываете?
Ага, не учитываю, поскольку ещё не умею, а подсказать некому. :(
Однако, сначала надо определиться, какой будет ли выигрыш в производительности.
Угу, складываете вы параллельно к примеру 555....5555 и 444....4445. И у вас возник перенос в последнем разряде. Что толку от параллельного сложения циферок, если потом этот перенос надо будет последовательно по всем разрядам тащить? С умножением будет не лучше.
...
Рейтинг: 0 / 0
C++ BigIntegers parallel library
    #38392390
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
?Что толку от параллельного сложения циферок, если потом этот перенос надо будет
последовательно по всем разрядам тащить? С умножением будет не лучше.
Ш-ш-ш-ш, не спойлери. Дай ему пройти по всем граблям, иначе образовательного эффекта не будет.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
C++ BigIntegers parallel library
    #38392400
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SerValmaytonSerVal, а какие задачи ты решаешь? Криптография?
Не, сам я в криптографии не разбираюсь. Но есть ребятки, которые интересуются криптоанализом шифров Bivium и Trivum.

Чел, ну насколько я знаю, крипто-библиотеки просто используют MMX/SSE наборы команд чтобы работать
с длинной арифметикой. Причём у них длинная арифметика изначально, на уровне постановки ограничена
в разрядности. К примеру задались регистром в 512 бит. И работают с такими регистрами. Если там
умножение или сложение - то обычно по модулю. Тоесть переноса в самый старший разряд нету. Из
этого и танцуют. Юзать для криптографии BigInteger - ну не знаю. Наверное это слишком уж Generic-решение.

И что у тебя вообще за операции? На высоком уровне. Разложение на множители?

Я к тому что есть разные подходы к оптимизации.
...
Рейтинг: 0 / 0
C++ BigIntegers parallel library
    #38392436
SerVal
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
GuestУгу, складываете вы параллельно к примеру 555....5555 и 444....4445. И у вас возник перенос в последнем разряде. Что толку от параллельного сложения циферок, если потом этот перенос надо будет последовательно по всем разрядам тащить? С умножением будет не лучше.
Ну, если бы перенос возникал только в последнем разряде - всё было бы просто:
добавить единичку в старший разряд при сложении или остаток от деления на 10 при умножении(при базе=10) :)

Однако ж, проблема давно известна, и, разумеется, решена: никто переносы последовательно не тащит. Вот тут
"Введение в параллельные и распределённые алгоритмы": описано параллельное сложение больших чисел:
http://www.toves.org/books/distalg/#3.3
Однако ж, реализации нетути. То что на аглицком, это ещё ладно. Похоже, там какие-то недоговорённости, не позволяющие ущучить смысл и реализовать на С++. Ну, или у меня недостаточно мозгов(что тоже не исключается).
Больше никакой теории найти не могу. На русском - и подавно(всё в закромах Родины).

Ежели кто знает как реализовать параллельный сумматор с переносами, прошу поделиться ссылкой(на или алгоритм или реализацию). А то чёта всё застопорилось. :(
...
Рейтинг: 0 / 0
C++ BigIntegers parallel library
    #38392443
m_Sla
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SerValДобрый день, m_Sla .

Про n1.add(n2) - какое ж это сложение?
Это не "А= В+С", а реализация оператора "+=". -> A += B
- теряется одно из слагаемых - оно становится результатом.
...это как говорят в Одессе - две большие разницы. :)
...У меня почти тоже самое:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
void BigInt::add(BigInt& summand)
{
    vector<char> rez; //все равно создаю временное хранилище
    ...

    number=rez; // а потом копирую новый результат
}

Знаю, что не оптимально, но мне переделывать лень. )))
...
Рейтинг: 0 / 0
C++ BigIntegers parallel library
    #38392453
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SerValстрока1 : 100000000 цифр.
строка2 : 100000000 цифр.
Конструируем 2 числа:
Exec time : 7.85 seconds.
==================
CPU: A = add(B,C)
Exec time : 17 seconds.

У меня больше 100 мс на сложение не получается. Даже миллиард цифр в секунду укладывается.
Безо всякой оптимизации.
Вот тупо за 5 мин накидал код. Дарю.

Код: plaintext
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.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
144.
145.
#include <iostream>
#include <iomanip>
#include <fstream>
#include <string>
#include <algorithm>
#include <vector>
#include <typeinfo>
#include <boost/date_time.hpp>
#include <boost/lexical_cast.hpp>

using namespace std;

std::string gen_dec_string(size_t len)
{
    std::string res;
    res.reserve(len);
    for (size_t i = 0; i != len; ++i) {
        char ch = '0' + rand() % 10;
        res += ch;
    }
    return res;
}

struct timing
{
    boost::posix_time::ptime t;
    size_t num;
    timing()
    {
        t = boost::posix_time::microsec_clock::universal_time();
        num = 0;
    }
    void print(const std::string& msg)
    {
        cout << (++num) << ": " <<  msg << ": " << (boost::posix_time::microsec_clock::universal_time() - t) << endl;
        t = boost::posix_time::microsec_clock::universal_time();
    }
    void start()
    {
        t = boost::posix_time::microsec_clock::universal_time();
    }
};



class BigInt
{
public:
    BigInt() { set("0"); }
    BigInt(const std::string& str) { set(str); }
    void set(const std::string& str);
    void add(const BigInt& o);
    std::string to_string() const;

private:
    std::vector<boost::uint32_t> data; // base-1e9 encoded decimal, LE ordering
    static const size_t base_len = 9;
    static const boost::uint32_t base = 1000000000ul;
    //static const size_t base_len = 1; // даже так дает до 1 сек сложение
    //static const boost::uint32_t base = 10ul;
};

void BigInt::set(const std::string& str)
{
    assert(!str.empty());
    data.clear();
    data.reserve(str.size() / base_len + 2);
    size_t pos;
    for (pos = str.size(); pos >= base_len; pos -= base_len) {
        boost::uint32_t digit = boost::lexical_cast<boost::uint32_t>(str.substr(pos - base_len, base_len));
        data.push_back(digit);
    }
    if (pos) {
        data.push_back(boost::lexical_cast<boost::uint32_t>(str.substr(0, pos)));
    }
}

string BigInt::to_string() const
{
    assert(!data.empty());
    std::string res;
    res.reserve(data.size() * base_len);
    char buf[10];
    const char* format = "%u";
    for (size_t i = data.size(); i != 0; --i) {
        sprintf(buf, format, data[i - 1]);
        res += buf;
        format = "%09u";
    }
    return res;
}

void BigInt::add(const BigInt& o)
{
    assert(!data.empty());
    assert(!o.data.empty());
    if (data.size() < o.data.size()) {
        data.reserve(o.data.size() + 1);
        data.resize(o.data.size() + 1);
    }
    boost::uint32_t carry = 0;
    for (size_t i = 0; i != o.data.size(); ++i) {
        carry += data[i] + o.data[i];
        if (carry >= base) {
            data[i] = carry - base;
            carry = 1;
        }
        else {
            data[i] = carry;
            carry = 0;
        }
    }
    if (carry) {
        if (data.size() > o.data.size()) {
            data[o.data.size()] += carry;
        }
        else {
            data.push_back(carry);
        }
    }
}




int main()
{
    timing t;
    t.start();
    std::string n1s = gen_dec_string(100000000);
    t.print("gen n1");
    t.start();
    BigInt n1(n1s);
    t.print("init n1");
    t.start();
    std::string n2s = gen_dec_string(100000000);
    t.print("gen n2");
    t.start();
    BigInt n2(n1s);
    t.print("init n2");
    t.start();
    n1.add(n2);
    t.print("add n1 += n2");
    return 0;
}


...
Рейтинг: 0 / 0
C++ BigIntegers parallel library
    #38392498
SerVal
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Добрый день, mayton .
maytonЮзать для криптографии BigInteger - ну не знаю. Наверное это слишком уж Generic-решение.
И что у тебя вообще за операции? На высоком уровне. Разложение на множители?
Я к тому что есть разные подходы к оптимизации.
У ребят есть свой программист на зарплате. Он им сейчас на КУДЕ делает.

Библиотека нужна мне. Ну, скажем для личных нужд. Никаких денех я за это не получаю, и в обозримом будущем не получу.
По работе я ничего не программирую. Я, вообще, не программист. С++ для меня не более, чем удобный калькулятор.
(C# тоже годится, но уж больно медленный). Ну вот захотелось мне попроверять кое-что.. у каждого свои тараканы в голове...

А числа большие, даже в памяти не помещаются. Вот и пришла мне мысль, что вычисляя параллельно на 1600 процессорах результат можно получить немного быстрее, чем на одном. Началось, как писал выше, с поиска подходящей библиотеки..которой, как оказалась нетути. Точнее, у "Cray MP" она есть.. у меня нетути. *как-то Таг :)

*простые числа, разложение на множители.. это тоже. :)
...
Рейтинг: 0 / 0
C++ BigIntegers parallel library
    #38392528
SerVal
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Ребятки, спасибо за отклики. Я сейчас внимательно всё посмотрю и отвечу.
Однако ж и меня к вам вопрос: Вы на самом деле считаете, что вычисления на 1600 процессорах медленнее, чем на одном???
Интересно, как бы вы рассуждали, будь у вас в процессоре хотя бы 1000 ядер?

*ладно, ладно.. помнится во времена, когда "процессоры Интел ускоряли Интернет" нам обещали 80 ядер. Ну, хоть 80. :)
...
Рейтинг: 0 / 0
C++ BigIntegers parallel library
    #38392538
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SerValА числа большие, даже в памяти не помещаются. Вот и пришла мне мысль, что вычисляя параллельно на 1600 процессорах результат можно получить немного быстрее, чем на одном. Началось, как писал выше, с поиска подходящей библиотеки..которой, как оказалась нетути. Точнее, у "Cray MP" она есть.. у меня нетути. *как-то Таг :)

*простые числа, разложение на множители.. это тоже. :)
Я думаю что это забавный мозговой эксперимент. Сама по себе задача сложения многоразрядных
чисел давно вдоль и поперёк изъезжена и ничего здесь поделать нельзя. Яркий пример - деление
или нахождение остатка от деления. Операция принципиально несократимая. Ее можно иногда
задавать таблично, иногда что-то кешировать но один хрен она - тот самый гранит который грызут
все криптоаналитики. По сути она-же защищает наши засекюренные файлы от "жены" и "спецслужб".
(подчеркнуть что опаснее !).

А если серъезно - то факторизация гораздо интереснее чем то чем ты занят. Поинтересуйся как-нибудь.
Можно зацепить краем теорвер, теорию чисел, алгебру.
...
Рейтинг: 0 / 0
C++ BigIntegers parallel library
    #38392541
?
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
?
Гость
SerValъПохоже, там какие-то недоговорённости, не позволяющие ущучить смысл и реализовать на С++ну там отсылка к разделу 3.1 (parallel prefix scan) - это самая сложная часть.
...
Рейтинг: 0 / 0
C++ BigIntegers parallel library
    #38392551
?
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
?
Гость
SerValЕжели кто знает как реализовать параллельный сумматор с переносами, прошу поделиться ссылкой(на или алгоритм или реализацию). А то чёта всё застопорилось. :( http://literaturki.net/elektronika/cifrovaya-shemotehnika1/165-parallelnye-summatory-s-parallelnym-perenosom (шутка)
...
Рейтинг: 0 / 0
C++ BigIntegers parallel library
    #38392565
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
maytonЯ думаю что это забавный мозговой эксперимент.
Скорее это очень хороший способ прокачать мозг ТСа. Возможно, в результате он дойдёт до уровня, достаточного для того, чтобы раскрыть один маленький секрет длинной арифметики:
гораздо эффективнее и проще распараллеливать конечный алгоритм чем элементарные операции.
...
Рейтинг: 0 / 0
C++ BigIntegers parallel library
    #38393118
m_Sla
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SerValОднако ж, проблема давно известна, и, разумеется, решена: никто переносы последовательно не тащит. Вот тут
"Введение в параллельные и распределённые алгоритмы": описано параллельное сложение больших чисел:
http://www.toves.org/books/distalg/#3.3
Однако ж, реализации нетути. То что на аглицком, это ещё ладно. Похоже, там какие-то недоговорённости, не позволяющие ущучить смысл и реализовать на С++. Ну, или у меня недостаточно мозгов(что тоже не исключается).
Больше никакой теории найти не могу. На русском - и подавно(всё в закромах Родины).

Ежели кто знает как реализовать параллельный сумматор с переносами, прошу поделиться ссылкой(на или алгоритм или реализацию). А то чёта всё застопорилось. :(реализация алгоритма на С в лоб, без всякой оптимизации и без распараллеливания
см. void BigInt::parallel_add(BigInt& s):
Код: plaintext
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.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
144.
145.
146.
147.
148.
149.
150.
151.
152.
153.
154.
155.
156.
157.
158.
159.
160.
161.
162.
163.
164.
165.
166.
167.
168.
169.
170.
171.
172.
173.
174.
175.
176.
177.
178.
179.
180.
181.
182.
183.
184.
185.
186.
187.
188.
189.
190.
191.
192.
193.
194.
195.
196.
197.
198.
199.
200.
201.
202.
203.
204.
205.
206.
207.
208.
209.
210.
211.
212.
213.
214.
215.
216.
217.
218.
219.
220.
#include <iostream>
#include <vector>
#include <string>
#include <cstring>

#include <stdio.h>      /* printf */
#include <time.h>       /* clock_t, clock, CLOCKS_PER_SEC */

#include "vectorclass.h" // http://www.agner.org/optimize/vectorclass.zip

using namespace std;

//=======================================================================
class BigInt
{
public:
    BigInt() { };

    void print();
    void fromString(const std::string& str);
    void add(BigInt& num);
    void parallel_add(BigInt& s);

    size_t getLength() const
    {
        return number.size();
    }

    enum Sign { negative = -1, zero = 0, positive = 1 };
private:
    Sign sign;
    vector<char> number;
};
//=======================================================================
void BigInt::print()
{
    cout<<endl<<"num size="<<number.size()<<endl<<"num=";
    for (int i=number.size()-1; i>=0; i--)
    {
        cout<< (char)(number[i]+'0');
    }
    cout<<endl;
}
//=======================================================================
void BigInt::fromString(const std::string& str)
{
    int str_size= str.size();
    if(str_size&15)
    {
        str_size = (str_size&0xfffffff0) + 16;
    }

    number.reserve(str_size+16);
    for (int i = str.size()-1; i>=0; i--)
    {
        number.push_back(str[i]-'0');
    }
}
//=======================================================================
void BigInt::add(BigInt& summand)
{
        //
}
//=======================================================================
void print_vector(vector<char> &v)
{
    for(size_t i=0,imax=v.size();i<imax;i++)
    {
        cout<<(char)(v[i]+'0')<<",";
    }
    cout<<endl;
}
//=======================================================================
char get_our_operator(char x, char y) //см. 3.3 табл.  x y | x &#8855; y
{
    if(y==0) //y==N?
    {
        return 0;
    }
    else if(y==1) //y==C?
    {
        return 1;
    }
    else // y == M
    {
        return x;
    }
}
//=======================================================================
//#define debug_output
void BigInt::parallel_add(BigInt& s)
{
    size_t summand_size=s.number.size();
    if(number.size() < summand_size)
    {
        number.reserve(summand_size+1);
        number.resize(summand_size);
    }

    vector<char> carry;
    vector<char> summand=s.number;

    carry.reserve(number.size()+1);
    carry.resize(number.size()+1);
    summand.reserve(number.size());
    summand.resize(number.size());

    #ifdef debug_output
    cout<<endl<<"== Add =="<<endl;
    print_vector(number);
    print_vector(summand);
    #endif

    //заполняем <c>
    for(size_t i=0,imax=number.size();i<imax;i++)
    {
        char sum=number[i]+summand[i];
        if(sum > 9)
        {
            carry[i]=1; // C
        }
        else if(sum == 9)
        {
            carry[i]=2; // M
        }
        else
        {
            carry[i]=0; // N
        }
    }
    #ifdef debug_output
    print_vector(carry);
    #endif

    // заполняем <prefix scan>, сразу оставляем 0( нет переноса - N или M ) или 1 ( есть перенос - С )
    char total = carry[0];
    carry[0] = total & 1;
    for(size_t i=1,imax=number.size();i<imax;i++)
    {
        total=get_our_operator(total,carry[i]);
        carry[i]= total & 1;
    }
    #ifdef debug_output
    print_vector(carry);
    #endif

    // из <prefix scan> получаем <carries>
    memmove(carry.data()+1,carry.data(),carry.size()-1);
    carry[0]=0;
    #ifdef debug_output
    print_vector(carry);
    #endif

    //сложение
    for(size_t i=0,imax=number.size();i<imax;i++)
    {
        number[i]=(number[i] + summand[i] + carry[i]) % 10;
    }
    if(carry.back()==1)
    {
        number.push_back(1);
    }
    #ifdef debug_output
    print_vector(number);
    #endif
}
//=======================================================================
int main()
{
    BigInt n1,n2;
    string num1,num2;

    clock_t t;

    t = clock();

    const size_t NUMBER_OF_DIGITS=10;

    num1.reserve(NUMBER_OF_DIGITS*10);
    num2.reserve(NUMBER_OF_DIGITS*10);
    for(size_t i=0; i<NUMBER_OF_DIGITS; i++)
    {
        num1+="1234567123";
        num2+="7654321765";
        //num2+="909999999";
    }
    //num1="1";

    t = clock() - t;
    printf ("==================\nConstruct 2 strings \nExec time : %f seconds.\n==================\n",((float)t)/CLOCKS_PER_SEC);

    t = clock();
    n1.fromString(num1);
    n2.fromString(num2);
    t = clock() - t;
    printf ("Construct 2 numbers \nExec time : %f seconds.\n==================\n",((float)t)/CLOCKS_PER_SEC);

    if(n1.getLength()>1000)
    {
        cout<<"n1.size="<<n1.getLength()<<endl;
        cout<<"n2.size="<<n2.getLength()<<endl;
    }
    else
    {
        n1.print();
        n2.print();
    }

    t = clock();
    //n1.add(n2);
    n1.parallel_add(n2);
    t = clock() - t;
    printf ("CPU: A = parallel_add(B,C)\nExec time : %f seconds.\n==================\n",((float)t)/CLOCKS_PER_SEC);

    if(n1.getLength()<=1000) n1.print();

    cout<<"add.size="<<n1.getLength()<<endl;

    return 0;
}

P.S. сильно не проверял, возможны ошибки
...
Рейтинг: 0 / 0
C++ BigIntegers parallel library
    #38393163
?
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
?
Гость
m_Slaреализация алгоритма на С в лоб, без всякой оптимизации и без распараллеливания
см. void BigInt::parallel_add(BigInt& s):Дык, там все самое сложное в распараллеливании prefix scan. А вы его циклом сделали, который не распараллеливается. А остальное то элементарно.
...
Рейтинг: 0 / 0
C++ BigIntegers parallel library
    #38393231
m_Sla
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
?m_Slaреализация алгоритма на С в лоб, без всякой оптимизации и без распараллеливания
см. void BigInt::parallel_add(BigInt& s):Дык, там все самое сложное в распараллеливании prefix scan. А вы его циклом сделали, который не распараллеливается. А остальное то элементарно.ну так надо ТСу, а не мне
пусть распараллеливает
...
Рейтинг: 0 / 0
C++ BigIntegers parallel library
    #38393986
SerVal
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
2 Anatoly Moskovsky :
Посмотрел Ваш подарок. Аппетитный такой подарок, спасибо. *правда, в нём непонятная библиотека boost. Про буст я не знаю.

m_Sla , Вы молодец, разобрались. Спасибо. Правда в Вашем коде я пока разобраться не могу.
Однако ж сам дошёл до получения вектора <carry>. Получить из <prefix scan> <carries> пока не получается. :(
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
a:                < 9, 7, 5, 3, 1> 
b:                < 3, 2, 1, 8, 6> 
c:                < C, M, N, C, N> 
prefix scan:  < C, C, N, C, N> 
carries:        < 0, 1, 1, 0, 1> 
sum:            < 2, 0, 7, 1, 8> 

// из <prefix scan> получаем <carries>
   memmove(carry.data()+1,carry.data(),carry.size()-1);
   carry[0]=0;



Как Вы получаете из <prefix scan> <carries> - ещё непонятнее. Каким-то копированием памяти? ??? Совсем непонятно.
Я пробую так:
Код: plaintext
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.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
#define _carry_ 'C'
#define _maybe_ 'M'
#define _never_ 'N'

char carryPlusOps(char x,char y)
{
	if((x==_never_) & (y==_never_)) return _never_;
	if((x==_never_) & (y==_maybe_)) return _never_;
	if((x==_never_) & (y==_carry_)) return _carry_;
	
	if((x==_maybe_) & (y==_never_)) return _never_;
	if((x==_maybe_) & (y==_maybe_)) return _maybe_;
	if((x==_maybe_) & (y==_carry_)) return _carry_;

	if((x==_carry_) & (y==_never_)) return _never_;
	if((x==_carry_) & (y==_maybe_)) return _carry_;
	if((x==_carry_) & (y==_carry_)) return _carry_;

	return x;
}

void addParallel()
{
	// заполняем цифрами из примера:
	std::vector<int> a; // <9,7,5,3,1>
	a.push_back(9); a.push_back(7); a.push_back(5);	a.push_back(3); a.push_back(1);

	std::vector<char> b; // < 3, 2, 1, 8, 6>
	b.push_back(3); b.push_back(2); b.push_back(1); b.push_back(8); b.push_back(6);
	// Ок.

	// заполняем <c> 
	std::vector<char> c(a.size(),0); // < C, M, N, C, N> 
	for(int idx=0; idx <c.size(); idx++)
	{
		int ab_sum=a[idx] + b[idx];
		if(ab_sum>=10) c[idx]= _carry_;
		else
			if(ab_sum<9) c[idx]= _never_;
			else c[idx]= _maybe_;
	}
	// Ок. <c> cоответствует.

	// заполняем <prefix scan> 
	std::vector<char> prefix_scan(c.size()); // < C, C, N, C, N> 

	char total = c[0];
    prefix_scan[0] = total;
	 
	for(size_t i=1; i< a.size(); i++)
    {
		total=carryPlusOps(total,c[i]);
		prefix_scan[i]= total;
	}
	// Ок. prefix_scan cоответствует.

	// заполняем carry
	std::vector<int> carry(a.size(), 0); // < 0, 1, 1, 0, 1>  

	for(int idx=0; idx<carry.size(); idx++)
	{
		if(prefix_scan[idx]== _carry_)
				carry[idx] = 1;
	}
	// !!! === Фигу. не соответствует. === !!! :( 

	carry[0]=0;
	// складываем, учитывая переносы
	std::vector<int> out(a.size()); 
	for(size_t n=0;  n<a.size(); n++)
	{
		out[n]= a[n]+b[n]+carry[n];
		if(out[n]>=10) out[n]-=10; 
	}
	// если есть перенос в старшем разряде - увеличить число цифр на 1.
	if(carry.back() > 0)
		out.push_back(carry.back());
	
	// out < 2, 0, 7, 1, 8> 
}


Векторы независимые, чтобы после того как заработает, распараллелить. Тружусь..
Всем привет и хорошего настроения. :)
...
Рейтинг: 0 / 0
C++ BigIntegers parallel library
    #38393997
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SerValправда, в нём непонятная библиотека boost. Про буст я не знаю.
...
Рейтинг: 0 / 0
C++ BigIntegers parallel library
    #38394006
SerVal
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
maytonА если серьёзно - то факторизация гораздо интереснее чем то чем ты занят. Поинтересуйся как-нибудь.
Можно зацепить краем теорвер, теорию чисел, алгебру.
Этим всё равно придётся заняться. Патамушта держать в памяти BigInt-ы (векторы с миллиардом знаков) - это ж никакой памяти не хватит. Только для примеров.
Если число долго не используется, может быть есть смысл хранить его в факторизованном виде. Или как-то упакованным. А при необходимости - распаковывать. Но пока об этом рано говорить. Этим можно заняться после базовых операций(сложение, умножение..). Факторизация, в этом случае, тоже должна быть быстрой. Думаю, и тут 1600 процессоров помогут. :)
...
Рейтинг: 0 / 0
C++ BigIntegers parallel library
    #38394039
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SerVal, простые числа (prime numbers) не раскладываются на можнители. В этом кстати и соль
этой задачи - в поиске подобных чисел.

Природа кстати такие задачи обходит и просто не решает. Просто ей не нужна чисельная точность
до младшего разряда. Тот-же double или extended можно рассматривать как как biginteger но
с экспоненциальной сеткой. Тоесть чем больше число - тем грубее у него абсолютная погрешность.

Можно удобно посчитать соотношение поперечника вселенной к диаметру электрона и решить
это в double и получить вполне вменяемый с точки зрения физики ответ.

В твоих числах для решения этой задачи толку нет. Мы всё равно не можем с точностью
до микрометра посчитать поперечник вселенной. Погрешности числителя и знаменателя
разные.

Улавливаешь?
...
Рейтинг: 0 / 0
C++ BigIntegers parallel library
    #38394069
SerVal
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
mayton , простые числа тоже как-то хранят. Типа 2^n+1. Мож и остальные так хранить.
Ну а насчёт природы.. ээ.. Неперу про его логарифмы чего только не говорили.. Лет 300 оне без применения лежали. :)
...
Рейтинг: 0 / 0
C++ BigIntegers parallel library
    #38394075
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ты нарисовал формулу похожую на "числа Мерсена". С некоторым отличием там минус 1 а не плюс. Отлично.
Но это не все простые числа а лишь ничтожно малая их часть. Кроме того тебе никто не обещал сжатия
места после факторизации. Это ты сам неверное придумал? Факторизация она ... для других дел.

Я про то что физика, как наука о природе довольствуется расчётами в double. Ей не нужны копейки в младших
разрядах.

Так-то...
...
Рейтинг: 0 / 0
25 сообщений из 104, страница 3 из 5
Форумы / C++ [игнор отключен] [закрыт для гостей] / C++ BigIntegers parallel library
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]