>>
>>Чтобы дать осмысленный ответ нужно знать подробности:
>
>да запросто. пример тестовый без авторских прав :)
>
>
> #pragma omp parallel private(i, p, j)
> {
> #pragma omp for schedule(dynamic)
> for (i = 0; i < mis.size(); ++i) {
> p = &mis[i]->second.v;
>
> for (j = 0; j < p->size(); ++j) {
> delete (*p)[j];
> }
>
> p->clear();
> }
> }
>
>процессоров 2 PowerPC_Power4, 6 гиг озу, скоко кеша не знаю
>потоков 2. aix дефолтом выставляет. определял и через OMP_NUM_THREADS.
>
Ага. Ну вот теперь все гораздо понятней.
(У меня, правда, Solaris, но все выглядит очень похоже)
первым делом запускаем это дело под профилировщиком.
В моем случае это Performance Analyzer из Sun Studio.
Два раза: для OMP_NUM_THREADS=1 и OMP_NUM_THREADS=2
видим почти одинаковые картинки, но для двух потоков
лишнее время тратится на функции из malloc.h, и libc-шную синхронизацию.
Вспоминаем, что обычный malloc с друзьями
"mt safe, not mt hot". Проверяем на чем-нибудь попроще
чем изначальный пример на C++
Пишу программу с openmp которая много раз маллочит и реаллочит.
Убеждаюсь, что чем больше потоков тем хуже.
#pragma omp parallel for
for(i=0; i<N; i++) {
p[i] = malloc(1);
for (j=0; j<1000; j++) {
p[i] = realloc(p[i], 1);
}
}
-bash-3.00$ cc -xO4 t.c -xopenmp
-bash-3.00$ export OMP_NUM_THREADS=1; time ./a.out
real 0m7.469s
user 0m7.462s
sys 0m0.005s
-bash-3.00$ export OMP_NUM_THREADS=2; time ./a.out
real 0m29.631s
user 0m55.658s
sys 0m1.110s
Что же делать? Нужен другой аллокатор!
На Солярисе есть libumem. Попробуем:
-bash-3.00$ cc -xO4 t.c -xopenmp -lumem
-bash-3.00$ export OMP_NUM_THREADS=1; time ./a.out
real 0m5.768s
user 0m5.734s
sys 0m0.005s
-bash-3.00$ export OMP_NUM_THREADS=2; time ./a.out
real 0m2.756s
user 0m5.761s
sys 0m0.006s
Полегчало. Теперь к исходному примеру:
-bash-3.00$CC -xO4 t.cc -xopenmp -lumem
-bash-3.00$ export OMP_NUM_THREADS=1; time ./a.out
1 Before init : u =0; s =0
1 After init : u =27; s =1
1 After preparing for destroy : u =27; s =1
1 After destroy : u =47; s =2
real 0m50.877s
user 0m47.380s
sys 0m2.242s
-bash-3.00$ export OMP_NUM_THREADS=2; time ./a.out
1 Before init : u =0; s =0
1 After init : u =27; s =1
1 After preparing for destroy : u =27; s =1
1 After destroy : u =65; s =2
real 0m49.948s
user 1m5.873s
sys 0m2.114s
Ну вот, основной кусок починился.
Дальше сам.