Здравствуйте, Павел Кузнецов, Вы писали:
ПК>shardim,
>> Я вычитал чтобы решить проблему выделения памяти одновременно нескольким потоками >> надо использовать библиотеку LIBCMT.LIB. Но возникает другая проблема. При использовании >> этой библиотеки начинается синхронизация выделении памяти, или попросту выглядит это так >> пока одна команда new (malloc) не закончит выделение памяти другая будет находится в стадии >> ожидания. Ну а дальше сами судите как это отразиться на производительности.
ПК>В общем случае -- Нужно мерять.
>> Решением этой проблемы предлагают использовать кучи для каждого потока, >> но при такой работе надо пользоваться функциями HeapAlloc и HeapFree.
ПК>Эти функции точно так же содержат блокировки, поэтому вокруг них нужно будет много чего написать.
Здравствуйте, shardim, Вы писали:
RUM>>если ты в С новичок, то, скорее всего, тебе не надо с этим заморачиваться, тебе хватит одной кучи на всех (стандартной) RUM>>я прав?
S>Хоть новичок, а софт написать надо. Я же не из праздного любопытства этим занялся. Вот и спрашиваю совета у более опытных.
Совет более опытных состоит в том, что в большинстве случаев подобные проблемы не имеют решающего значения, и, соответственно, пока профайлер не покажет, что именно это является узким местом твоей программы, лучше туда не лезть, т.к. разделение куч по потокам исполнения является очень нетривиальным делом, заметно усложняющим программу как на макро-, так и на микроуровне.
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Подскажите новичку.
Написал программу которая может создавать несколько потоков.
Примерно выглядит следующим образом
main(...){
while(...) {
_beginthreadex(,,Mythread,,,);
}
}
Mythread(){
MyFunction1();
MyFunction2();
...
...
}
MyFunction1(){
char * x;
x=new char[10];
...
...
delete x;
}
MyFunction2(){
char * x1;
x1=new char[10];
...
...
delete x1;
}
Вопрос вот в чем.
Если я создам ну скажем 5 потоков, при вызове функций MyFunction1,MyFunction2,
потоки не будут между собой конфликтовать?
И вопрос по памяти.
Насколько вычитал оператор new получает блоки памяти из кучи процесса.
В каждом потоке я могу создать кучу (HeapCreate(...)), так вот будет ли
оператор new получать блоки памяти из созданной в потоке кучи?
А если не будет получать то как его заставить?
shardim,
> Если я создам ну скажем 5 потоков, при вызове функций MyFunction1,MyFunction2, > потоки не будут между собой конфликтовать?
Если у них нет разделяемых данных -- не должны. (В приведенном примере подобных данных не видно.)
> Насколько вычитал оператор new получает блоки памяти из кучи процесса.
Зависит от реализации конкретного компилятора и поставляемой с ним CRT.
> В каждом потоке я могу создать кучу (HeapCreate(...)), так вот будет ли > оператор new получать блоки памяти из созданной в потоке кучи?
Очень маловероятно: откуда ему вообще знать, что ты создал еще одну кучу?
> А если не будет получать то как его заставить?
Написать свой operator new. Лучше всего placement. (Дополнительную информацию искать по словам "placement new".)
Posted via RSDN NNTP Server 2.0
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Тут где-то проходил топик про ThreadSafe контайнер
и остановились на том что операция new не есть ThreadSafe так она должна
синхронизироваться на куче дабы не порушить её привыделении памяти одновременно несколькими процессами, так вот если создать каждому потоку свою кучу
и заставить опратор new ней работать то это и может быть решением.
Может это как раз тот случай
Здравствуйте, Павел Кузнецов, Вы писали:
ПК>Здравствуйте, shardim, Вы писали:
S>>А что если испьзовать HeapAlloc ну и подобные функции для работы с памятью.
ПК>А можно пояснить, зачем тебе по куче на каждый поток исполнения?
Здравствуйте.
Да serega это как раз то о чем я пытаюсь сказать.
Я вычитал чтобы решить проблему выделения памяти одновременно нескольким потоками
надо использовать библиотеку LIBCMT.LIB. Но возникает другая проблема. При использовании
этой библиотеки начинается синхронизация выделении памяти, или попросту выглядит это так
пока одна команда new (malloc) не закончит выделение памяти другая будет находится в стадии
ожидания. Ну а дальше сами судите как это отразиться на производительности.
Решением этой проблемы предлагают использовать кучи для каждого потока,
но при такой работе надо пользоваться функциями HeapAlloc и HeapFree.
Так вот, возможно заставить new (malloc) и delete (free) работать с кучей потока?
Жутко не хочется переделывать все new и delete.
Здравствуйте, shardim, Вы писали:
S>Здравствуйте. S>Да serega это как раз то о чем я пытаюсь сказать. S>Я вычитал чтобы решить проблему выделения памяти одновременно нескольким потоками S>надо использовать библиотеку LIBCMT.LIB. Но возникает другая проблема. При использовании S>этой библиотеки начинается синхронизация выделении памяти, или попросту выглядит это так S>пока одна команда new (malloc) не закончит выделение памяти другая будет находится в стадии S>ожидания. Ну а дальше сами судите как это отразиться на производительности. S>Решением этой проблемы предлагают использовать кучи для каждого потока, S>но при такой работе надо пользоваться функциями HeapAlloc и HeapFree.
S>Так вот, возможно заставить new (malloc) и delete (free) работать с кучей потока? S>Жутко не хочется переделывать все new и delete.
shardim,
> Я вычитал чтобы решить проблему выделения памяти одновременно нескольким потоками > надо использовать библиотеку LIBCMT.LIB. Но возникает другая проблема. При использовании > этой библиотеки начинается синхронизация выделении памяти, или попросту выглядит это так > пока одна команда new (malloc) не закончит выделение памяти другая будет находится в стадии > ожидания. Ну а дальше сами судите как это отразиться на производительности.
В общем случае -- Нужно мерять.
> Решением этой проблемы предлагают использовать кучи для каждого потока, > но при такой работе надо пользоваться функциями HeapAlloc и HeapFree.
Эти функции точно так же содержат блокировки, поэтому вокруг них нужно будет много чего написать.
> Так вот, возможно заставить new (malloc) и delete (free) работать с кучей потока?
Возможно. Но весьма нетривиально. Т.е. просто, "в лоб", подменить реализацию new и delete очень легко. Но вот реализовать delete/free без блокировок так, чтобы они умели корректно освобождать память, выделенную в другом потоке исполнения, весьма нетривиально. А делать это придется, т.к. сценариев, где (незаметно) возникает такая ситуация, достаточно много.
> Жутко не хочется переделывать все new и delete.
Может, сначала, все-таки, определить, насколько это реально нужно для твоего приложения?
Posted via RSDN NNTP Server 2.0
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Шахтер,
>>> Решением этой проблемы предлагают использовать кучи для каждого потока, >>> но при такой работе надо пользоваться функциями HeapAlloc и HeapFree. > > ПК>Эти функции точно так же содержат блокировки, поэтому вокруг них нужно будет много чего написать. > > Не совсем так. Это управляется флажками.
Спасибо за поправку. В таком случае к работе с ними применима дальнейшая часть сообщения
Ш>Будет ли браться критическая секция при выполнении операций. Ш>См. документацию по функциям в MSDN.
Ребят можно чуточку поподробней, я же новичок в Си.
По каким функциям смотреть в MSDN?
И при чем блокировка при использовании HeapAlloc и HeapFree,
ведь я для каждого потока создаю свою кучу, и другие потоки к этой куче
доступа не имеют. Ну и насколько я понял из прочитанного. блокировки между
потоками при выделении памяти не будет, т.к. каждый поток работает со своей
кучей.
А вы не боитесь нарваться на мертвые ссылки — типа создали что-то в потоке, а адрес передали в др поток, потом ваш поток завершился, снес свою кучу, а кто-то другой все еще держит адрес...
Также можете посмотреть в сторону std::allocator, т.к. он передается как шаблонный параметр в коллекции, но будьте осторожны (т.к. объекты в ваших коллециях будут юзать обычный new или свой allocator)
во-первых не delete, а delete[], хотя в данном случае разницы
S>MyFunction1(){ S> char * x; S> x=new char[10]; S> ... S> ... S> delete[] x; S>}
S>Вопрос вот в чем. S>Если я создам ну скажем 5 потоков, при вызове функций MyFunction1,MyFunction2, S>потоки не будут между собой конфликтовать?
в данном случае в каждом потоке x свое, поэтому конфликтов не должно быть
S>И вопрос по памяти. S>Насколько вычитал оператор new получает блоки памяти из кучи процесса. S>В каждом потоке я могу создать кучу (HeapCreate(...)), так вот будет ли S>оператор new получать блоки памяти из созданной в потоке кучи? S>А если не будет получать то как его заставить?
если ты в С новичок, то, скорее всего, тебе не надо с этим заморачиваться, тебе хватит одной кучи на всех (стандартной)
я прав?
Правило наименьшего удивления: Программа должна работать так, чтобы это вызывало наименьшее удивление у пользователя.
Построй свой мини-горд на http://rumactep.myminicity.com/
LM>А вы не боитесь нарваться на мертвые ссылки — типа создали что-то в потоке, а адрес передали в др поток, потом ваш поток завершился, снес свою кучу, а кто-то другой все еще держит адрес...
Бояться волков, в лес не ходить.
Из потока в поток я нечего не передаю.
Здравствуйте, Павел Кузнецов, Вы писали:
ПК>А можно пояснить, зачем тебе по куче на каждый поток исполнения?
Ну по куче на каждый поток наверное действительно,перебор. Но разве не бывает ситуаций, когда не желательно, чтобы несколько потоков лезли в одну и ту же кучу? Фрагментаия, например.
Здравствуйте, Alexander__S, Вы писали:
ПК>> А можно пояснить, зачем тебе по куче на каждый поток исполнения?
A__> Ну по куче на каждый поток наверное действительно,перебор. Но разве не бывает ситуаций, когда не желательно, чтобы несколько потоков лезли в одну и ту же кучу? Фрагментаия, например.
Разные могут быть случаи. Вполне может оказаться, что выигрыши от использования своих куч в каждом потоке вполне окупают затраты по организации соответствующего управления памятью. Собственно, есть даже вполне промышленные решения: http://www.hoard.org Просто мне показалось, что для автора оригинального сообщения проблема носит скорее виртуальный характер...
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Здравствуйте, shardim, Вы писали:
Ш>>Будет ли браться критическая секция при выполнении операций. Ш>>См. документацию по функциям в MSDN.
S>Ребят можно чуточку поподробней, я же новичок в Си.
Могу посоветовать почитать Рихтера тогда по API Win32.
S>По каким функциям смотреть в MSDN?
Есть 4 основные функции для работы с кучей.
HeapCreate
HeapDestroy
HeapAlloc
HeapFree
S>И при чем блокировка при использовании HeapAlloc и HeapFree, S>ведь я для каждого потока создаю свою кучу, и другие потоки к этой куче S>доступа не имеют.
Когда ты созздаёшь хип функцией HeapCreate, то внутри у него создаётся критическая секция, которая в дальнейшем будет использована при операциях HeapAlloc/HeapFree для многопоточной блокировки.
Если тебе это не нужно (когда у тебя однопоточное приложение или когда куча используется эксклюзивно одним потоком),
то эту фичу можно отключить передав при конструировании кучи флажок HEAP_NO_SERIALIZE.