Увеличение размера стека GCC или G++
Есть необходимость увеличения стека в С++. Как это возможно сделать для g++ или gcc.
для Linux - дефолтное ограничение можно посмотреть через ulimit -s. обычно это 8Мб. увеличте его через setrlimit и не надо трогать gcc
Что-то у вас с алгоритмом нелады. 8Мб памяти на стеке хватает для практически любых задач (даже космической сложности). Подозреваю, что у вас аргументы передаются копированием на стеке (по значению), а не через кучу (по ссылке), что для глубокой рекурсии равносильно отстрелу одной из нижних конечности из дедушкиного ружья (собственно, у вас это и происходит).
А вот пока никакой рекурсии в программе нет, и пока, не предвидится. Уж так построен алгоритм, только считай.
Если интересно можно распространяться и дальше на эту тему т.к. это мой диплом, а дальше и кандидатская.
История интересная. Только где в ней место малому стеку? ;)
Хмм, а вот про T++ я не слышал.
Если мне не изменяет память, в скифах есть(будут) и не-фоннеймановские вычислители, типа CUDA или ПЛИСок "толстых"? Тогда отсутствие рекурсии вполне понятно. :)
Соответственно, очень много зависит от того как эти данные передаются между фукнциями и как это реализуется на языков уровне T++. Покажите пример функции, для которой вам нужен большой стек. Hardcase вам уже намекал на это :)
Вот... даже все написано
http://ru.wikipedia.org/wiki/%D0%A2-%D0%A1%D0%B8%D1%81%D1%82%D0%B5%D0%BC%D0%B0
Википедиа - рулит!
Но не на стеке же это хранить, для сего существуют: куча, алоцируемые сегменты и, что самое веселое, отмапированные в память файлы.
PS: А по поводу T++ - очередной, свой "особенный" велосипед с колесами за ушами, созданный отечественными нанотехнологами в лучшем случае в виде ксерокса OpenMP, а то и тупого как пробка препроцессора к нему же.
PS: А по поводу T++ - очередной, свой "особенный" велосипед с колесами за ушами, созданный отечественными нанотехнологами в лучшем случае в виде ксерокса OpenMP, а то и тупого как пробка препроцессора к нему же.
Ну я бы не стал так прямо хаять "отчественного производителя". Все же T++ и OpenMP - это идеологически разные подходы, хотя реализация на уровне языка немного похожа (пичкаем код некоторыми декларациями).
"Идеологически разные подходы" это, видимо, распределенность вычислений по сети. Однако упс и где здесь идеологическая разница? А бытность особенными есть самое закоренелое заблуждение. Хотя нет - работа провЕдена, средствА освоены.
PS: А видимость "проделанной" работы реализуется посредством тройки студентов ваяющих макроподстановщик к МИТ'овскому бояну. Естественно никто из них ни в бумажках ни на словах никак не упоминается. Вот и вся "наука" на сегодняшний день. К сожалению.
Приходим к извечному спору, что лучше: императивные языки программирования или функциональные. Императивные языки программирования проще для понимания и работы, функциональные - мозги свернешь, пока придумаешь, зато нигде не говориться, что используется понятие потока, процесса или еще чего, что привязывает нас к архитектуре компьютера. Для первых нужен простой компилятор, который "не думает", как надо параллелить - все написано в программе, для вторых нужен "умный" компилятор, которые "должен думать", как параллелить.
Это не доказано, но, опять же, теоритики утверждают, что функциональный подход обладает бОльшим потенциалом параллелизма. Так что в свете удвоения количества ядер в процессоре примерно каждые два года, мы скоро очень быстро устанем их программировать и потребуется нечто, похожее на T++.
В обоих случаях параллелизм описывается явно в OpenMP прагмами, а в T++ ключевыми словами.
OpenMP
{
int x, y;
if ( n < 2 ) return n;
#pragma omp task shared(x)
x = fib(n - 1);
#pragma omp task shared(y)
y = fib(n - 2);
#pragma omp taskwait
return x + y;
}
T++
{
return n < 2 ?
n : fib(n - 1) + fib(n - 2); // Здесь не забываем, что функция fib объявлена с tfun
}
А реализация в этом самом магическом T++ аля: жуем соурс препроцессором, разжовывающим новые ключевые слова в ядреную смесь макросов с добавлением магических инклудов, о них далее, далее сие поступает на вход к компилятору C++. А теперь про макросы и инклуды: посредством тех самых магических макросов генерятся активные функциональные объекты с контекстом, посредством месива (из подсасонных инклудов) из все тех же макросов, классов, шаблонов, да чего там только нет, а в каком виде...
Итого: Посмотрев код, моя опала o_O. Авторы заслуживают как минимум маек с надписями "Master of Achtung!!!" ибо они похоже ушли в самадхи и уже очень давно. Да, это наше родное, преклоняюсь.
Странно что код приведен из википедии. При таком запале стоило бы приводить фрагменты рабочего кода - явно демонстрирующего бдыдлокодерство разработчиков.
Странно что код приведен из википедии. При таком запале стоило бы приводить фрагменты рабочего кода - явно демонстрирующего бдыдлокодерство разработчиков.
Да пожалуйста, это то что получается на выходе из преепроцессора:
TFUNIMPL(int, fib, (int n), (n), /*static*/, int n ;, { ts::Freezer _f; ts::ParentTemporaryOn _p(_tf); _tf->n = n; } ;, , )
{
return n < 2 ? n : fib(n-1) + fib(n-2);
}
А это кусочег магического хедера, в нем еще семь с половиной тысяч строчег аналогичного кода:
#define TFUNDEF(type,fun,pars,purepars,stas,args,argi,outs,outi) \
extern ts::TFunCtxt fun##TFunCtxt; \
struct fun##TArgDef { args ts::TFunCtxt* _fid; }; \
struct fun##TFunDef: public ts::TFun<type, fun##TFunCtxt>, fun##TArgDef { \
outs \
virtual ts::TFrz<type> body() = 0; \
static fun##TFunDef* New(); \
}; \
type fun##Cversion pars; \
static inline ts::TFrz<type> fun pars { \
ts::TSLocker _l; \
MAYBE_C_CALL(type,fun,purepars); \
fun##TFunDef *_tf = fun##TFunDef::New(); \
argi \
_tf->stopAndContParent(); \
_tf = (fun##TFunDef*)fun##TFunDef::tryToReuseMemo(_tf,(fun##TArgDef*)_tf,sizeof(fun##TArgDef)); \
outi \
return _tf->retfrz; \
}
// Add tct here
#define TFUNIMPL(type,fun,pars,purepars,stas,args,argi,outs,outi) \
ts::TFunCtxt fun##TFunCtxt(#fun);\
struct fun##TArgImpl { args ts::TFunCtxt* _fid; }; \
struct fun##TFunImpl: public ts::TFun<type,fun##TFunCtxt>, fun##TArgImpl { \
outs stas \
virtual ts::TFrz<type> body(); \
virtual ts::SData* clone(); \
}; \
ts::SData* fun##TFunImpl::clone() { \
size_t extra = ts::Task::get_extra(); \
ts::SData* p = \
(ts::SData*)(new(extra) fun##TFunImpl(*this)); \
if (extra > 0) \
memcpy((char*)p + sizeof(fun##TFunImpl),(char*)this + sizeof(fun##TFunImpl),extra); \
return p; \
} \
fun##TFunDef* fun##TFunDef::New() { \
size_t extra = ts::Task::get_extra(); \
fun##TFunDef* p = (fun##TFunDef*)(new(extra) fun##TFunImpl); \
p->_fid = &fun##TFunCtxt; \
ts::Task::after_ctor(p); \
return p; \
} \
ts::TFrz<type> fun##TFunImpl::body()
PS: Запала никакого нет. Это тупой беглый анализ на пять минут.
Мне кажется, в этом месте заблуждение. Понятие "функция" не имеет никакого отношения к параллелизму. Хоть на Вики и написали, что она является гранулой параллелизма, но нигде явно не сказано, что если указали tfun, то значит запуститься отдельный поток. Опять же... Если брать во внимание tvar-ы, то не факт, что вызов tfun-функции приведет к ее немедленному запуску в отдельном потоке.
В макросах, конечно, намешали чего-то много всего... Но не факт, что OpenMP выглядит прощще после препроцессинга. Да и надо бы разобраться, чего в макросах намешали-то.
Пока не убедительено, почитаю я подробнее про T++. Продолжение дискуссии на усмотрение участников.