[Bf-committers] [Bf-blender-cvs] SVN commit: /data/svn/bf-blender [52908] trunk/blender/source/blender: use openmp to thread some common bmesh operations

Campbell Barton ideasman42 at gmail.com
Wed Dec 12 08:21:37 CET 2012


On Wed, Dec 12, 2012 at 4:34 PM, Brecht Van Lommel
<brechtvanlommel at pandora.be> wrote:
> Hi,
>
> I'd be careful testing if this actually speeds things up, threading
> overhead can be big especially on Xeon CPU's (maybe because they are
> multi socket and not just multi core). For subsurf it only uses openmp
> if the number of faces is > 1 million, otherwise it slowed down the
> modifier stack a lot rendering Sintel scenes.
>
> Brecht.
>
> On Wed, Dec 12, 2012 at 6:04 AM, Campbell Barton <ideasman42 at gmail.com> wrote:
>> Revision: 52908
>>           http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-blender&revision=52908
>> Author:   campbellbarton
>> Date:     2012-12-12 05:04:01 +0000 (Wed, 12 Dec 2012)
>> Log Message:
>> -----------
>> use openmp to thread some common bmesh operations
>> - BM_mesh_elem_toolflags_ensure / bmo_flag_layer_alloc / bmo_flag_layer_free / bmo_flag_layer_clear
>> - BM_mesh_select_flush
>> - EDBM_index_arrays_init
>>
>> notes:
>> - mostly use openmp `sections` to split operations on vert/edge/face since this is a fairly minor change.
>> - split tool flag pool in 3, this means we can allocate exact sizes needed and iterate on them in threads without alloc'ing.
>>
>> Modified Paths:
>> --------------
>>     trunk/blender/source/blender/bmesh/bmesh_class.h
>>     trunk/blender/source/blender/bmesh/intern/bmesh_core.c
>>     trunk/blender/source/blender/bmesh/intern/bmesh_marking.c
>>     trunk/blender/source/blender/bmesh/intern/bmesh_mesh.c
>>     trunk/blender/source/blender/bmesh/intern/bmesh_operators.c
>>     trunk/blender/source/blender/editors/mesh/editmesh_utils.c
>>     trunk/blender/source/blender/modifiers/intern/MOD_decimate.c
>>
>> Modified: trunk/blender/source/blender/bmesh/bmesh_class.h
>> ===================================================================
>> --- trunk/blender/source/blender/bmesh/bmesh_class.h    2012-12-12 04:50:53 UTC (rev 52907)
>> +++ trunk/blender/source/blender/bmesh/bmesh_class.h    2012-12-12 05:04:01 UTC (rev 52908)
>> @@ -187,8 +187,9 @@
>>         /*element pools*/
>>         struct BLI_mempool *vpool, *epool, *lpool, *fpool;
>>
>> -       /*operator api stuff*/
>> -       struct BLI_mempool *toolflagpool;
>> +       /*operator api stuff (must be all NULL or all alloc'd)*/
>> +       struct BLI_mempool *vtoolflagpool, *etoolflagpool, *ftoolflagpool;
>> +
>>         int stackdepth;
>>         struct BMOperator *currentop;
>>
>>
>> Modified: trunk/blender/source/blender/bmesh/intern/bmesh_core.c
>> ===================================================================
>> --- trunk/blender/source/blender/bmesh/intern/bmesh_core.c      2012-12-12 04:50:53 UTC (rev 52907)
>> +++ trunk/blender/source/blender/bmesh/intern/bmesh_core.c      2012-12-12 05:04:01 UTC (rev 52908)
>> @@ -79,8 +79,8 @@
>>         }
>>
>>         /* allocate flags */
>> -       if (bm->toolflagpool) {
>> -               v->oflags = BLI_mempool_calloc(bm->toolflagpool);
>> +       if (bm->vtoolflagpool) {
>> +               v->oflags = BLI_mempool_calloc(bm->vtoolflagpool);
>>         }
>>
>>         if (!(create_flag & BM_CREATE_SKIP_CD)) {
>> @@ -133,8 +133,8 @@
>>         e->head.htype = BM_EDGE;
>>
>>         /* allocate flags */
>> -       if (bm->toolflagpool) {
>> -               e->oflags = BLI_mempool_calloc(bm->toolflagpool);
>> +       if (bm->etoolflagpool) {
>> +               e->oflags = BLI_mempool_calloc(bm->etoolflagpool);
>>         }
>>
>>         e->v1 = v1;
>> @@ -291,8 +291,8 @@
>>         f->head.htype = BM_FACE;
>>
>>         /* allocate flags */
>> -       if (bm->toolflagpool) {
>> -               f->oflags = BLI_mempool_calloc(bm->toolflagpool);
>> +       if (bm->ftoolflagpool) {
>> +               f->oflags = BLI_mempool_calloc(bm->ftoolflagpool);
>>         }
>>
>>         if (!(create_flag & BM_CREATE_SKIP_CD)) {
>> @@ -512,8 +512,8 @@
>>         if (v->head.data)
>>                 CustomData_bmesh_free_block(&bm->vdata, &v->head.data);
>>
>> -       if (bm->toolflagpool) {
>> -               BLI_mempool_free(bm->toolflagpool, v->oflags);
>> +       if (bm->vtoolflagpool) {
>> +               BLI_mempool_free(bm->vtoolflagpool, v->oflags);
>>         }
>>         BLI_mempool_free(bm->vpool, v);
>>  }
>> @@ -532,8 +532,8 @@
>>         if (e->head.data)
>>                 CustomData_bmesh_free_block(&bm->edata, &e->head.data);
>>
>> -       if (bm->toolflagpool) {
>> -               BLI_mempool_free(bm->toolflagpool, e->oflags);
>> +       if (bm->etoolflagpool) {
>> +               BLI_mempool_free(bm->etoolflagpool, e->oflags);
>>         }
>>         BLI_mempool_free(bm->epool, e);
>>  }
>> @@ -555,8 +555,8 @@
>>         if (f->head.data)
>>                 CustomData_bmesh_free_block(&bm->pdata, &f->head.data);
>>
>> -       if (bm->toolflagpool) {
>> -               BLI_mempool_free(bm->toolflagpool, f->oflags);
>> +       if (bm->ftoolflagpool) {
>> +               BLI_mempool_free(bm->ftoolflagpool, f->oflags);
>>         }
>>         BLI_mempool_free(bm->fpool, f);
>>  }
>> @@ -1785,8 +1785,8 @@
>>         bmesh_disk_edge_remove(f1loop->e, f1loop->e->v2);
>>
>>         /* deallocate edge and its two loops as well as f2 */
>> -       if (bm->toolflagpool) {
>> -               BLI_mempool_free(bm->toolflagpool, f1loop->e->oflags);
>> +       if (bm->etoolflagpool) {
>> +               BLI_mempool_free(bm->etoolflagpool, f1loop->e->oflags);
>>         }
>>         BLI_mempool_free(bm->epool, f1loop->e);
>>         bm->totedge--;
>> @@ -1794,8 +1794,8 @@
>>         bm->totloop--;
>>         BLI_mempool_free(bm->lpool, f2loop);
>>         bm->totloop--;
>> -       if (bm->toolflagpool) {
>> -               BLI_mempool_free(bm->toolflagpool, f2->oflags);
>> +       if (bm->ftoolflagpool) {
>> +               BLI_mempool_free(bm->ftoolflagpool, f2->oflags);
>>         }
>>         BLI_mempool_free(bm->fpool, f2);
>>         bm->totface--;
>>
>> Modified: trunk/blender/source/blender/bmesh/intern/bmesh_marking.c
>> ===================================================================
>> --- trunk/blender/source/blender/bmesh/intern/bmesh_marking.c   2012-12-12 04:50:53 UTC (rev 52907)
>> +++ trunk/blender/source/blender/bmesh/intern/bmesh_marking.c   2012-12-12 05:04:01 UTC (rev 52908)
>> @@ -44,8 +44,6 @@
>>
>>  static void recount_totsels(BMesh *bm)
>>  {
>> -       BMIter iter;
>> -       BMElem *ele;
>>         const char iter_types[3] = {BM_VERTS_OF_MESH,
>>                                     BM_EDGES_OF_MESH,
>>                                     BM_FACES_OF_MESH};
>> @@ -58,11 +56,16 @@
>>         tots[1] = &bm->totedgesel;
>>         tots[2] = &bm->totfacesel;
>>
>> +#pragma omp parallel for schedule(dynamic)
>>         for (i = 0; i < 3; i++) {
>> -               ele = BM_iter_new(&iter, bm, iter_types[i], NULL);
>> -               for ( ; ele; ele = BM_iter_step(&iter)) {
>> -                       if (BM_elem_flag_test(ele, BM_ELEM_SELECT)) *tots[i] += 1;
>> +               BMIter iter;
>> +               BMElem *ele;
>> +               int count = 0;
>> +
>> +               BM_ITER_MESH (ele, &iter, bm, iter_types[i]) {
>> +                       if (BM_elem_flag_test(ele, BM_ELEM_SELECT)) count += 1;
>>                 }
>> +               *tots[i] = count;
>>         }
>>  }
>>
>> @@ -161,34 +164,45 @@
>>
>>         int ok;
>>
>> -       BM_ITER_MESH (e, &eiter, bm, BM_EDGES_OF_MESH) {
>> -               if (!(BM_elem_flag_test(e->v1, BM_ELEM_SELECT) &&
>> -                     BM_elem_flag_test(e->v2, BM_ELEM_SELECT) &&
>> -                     !BM_elem_flag_test(e, BM_ELEM_HIDDEN)))
>> +       /* we can use 2 sections here because the second loop isnt checking edge selection */
>> +#pragma omp parallel sections
>> +       {
>> +#pragma omp section
>>                 {
>> -                       BM_elem_flag_disable(e, BM_ELEM_SELECT);
>> +                       BM_ITER_MESH (e, &eiter, bm, BM_EDGES_OF_MESH) {
>> +                               if (!(BM_elem_flag_test(e->v1, BM_ELEM_SELECT) &&
>> +                                     BM_elem_flag_test(e->v2, BM_ELEM_SELECT) &&
>> +                                     !BM_elem_flag_test(e, BM_ELEM_HIDDEN)))
>> +                               {
>> +                                       BM_elem_flag_disable(e, BM_ELEM_SELECT);
>> +                               }
>> +                       }
>>                 }
>> -       }
>>
>> -       BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) {
>> -               ok = TRUE;
>> -               if (!BM_elem_flag_test(f, BM_ELEM_HIDDEN)) {
>> -                       l_iter = l_first = BM_FACE_FIRST_LOOP(f);
>> -                       do {
>> -                               if (!BM_elem_flag_test(l_iter->v, BM_ELEM_SELECT)) {
>> +#pragma omp section
>> +               {
>> +                       BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) {
>> +                               ok = TRUE;
>> +                               if (!BM_elem_flag_test(f, BM_ELEM_HIDDEN)) {
>> +                                       l_iter = l_first = BM_FACE_FIRST_LOOP(f);
>> +                                       do {
>> +                                               if (!BM_elem_flag_test(l_iter->v, BM_ELEM_SELECT)) {
>> +                                                       ok = FALSE;
>> +                                                       break;
>> +                                               }
>> +                                       } while ((l_iter = l_iter->next) != l_first);
>> +                               }
>> +                               else {
>>                                         ok = FALSE;
>> -                                       break;
>>                                 }
>> -                       } while ((l_iter = l_iter->next) != l_first);
>> -               }
>> -               else {
>> -                       ok = FALSE;
>> -               }
>>
>> -               if (ok == FALSE) {
>> -                       BM_elem_flag_disable(f, BM_ELEM_SELECT);
>> +                               if (ok == FALSE) {
>> +                                       BM_elem_flag_disable(f, BM_ELEM_SELECT);
>> +                               }
>> +                       }
>>                 }
>>         }
>> +       /* end sections */
>>
>>         /* Remove any deselected elements from the BMEditSelection */
>>         BM_select_history_validate(bm);
>> @@ -212,32 +226,42 @@
>>
>>         int ok;
>>
>> -       BM_ITER_MESH (e, &eiter, bm, BM_EDGES_OF_MESH) {
>> -               if (BM_elem_flag_test(e->v1, BM_ELEM_SELECT) &&
>> -                   BM_elem_flag_test(e->v2, BM_ELEM_SELECT) &&
>> -                   !BM_elem_flag_test(e, BM_ELEM_HIDDEN))
>> +       /* we can use 2 sections here because the second loop isnt checking edge selection */
>> +#pragma omp parallel sections
>> +       {
>> +#pragma omp section
>>                 {
>> -                       BM_elem_flag_enable(e, BM_ELEM_SELECT);
>> +                       BM_ITER_MESH (e, &eiter, bm, BM_EDGES_OF_MESH) {
>> +                               if (BM_elem_flag_test(e->v1, BM_ELEM_SELECT) &&
>> +                                   BM_elem_flag_test(e->v2, BM_ELEM_SELECT) &&
>> +                                   !BM_elem_flag_test(e, BM_ELEM_HIDDEN))
>> +                               {
>> +                                       BM_elem_flag_enable(e, BM_ELEM_SELECT);
>> +                               }
>> +                       }
>>                 }
>> -       }
>>
>> -       BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) {
>> -               ok = TRUE;
>> -               if (!BM_elem_flag_test(f, BM_ELEM_HIDDEN)) {
>> -                       l_iter = l_first = BM_FACE_FIRST_LOOP(f);
>> -                       do {
>> -                               if (!BM_elem_flag_test(l_iter->v, BM_ELEM_SELECT)) {
>> +#pragma omp section
>> +               {
>> +                       BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) {
>> +                               ok = TRUE;
>> +                               if (!BM_elem_flag_test(f, BM_ELEM_HIDDEN)) {
>> +                                       l_iter = l_first = BM_FACE_FIRST_LOOP(f);
>> +                                       do {
>> +                                               if (!BM_elem_flag_test(l_iter->v, BM_ELEM_SELECT)) {
>> +                                                       ok = FALSE;
>> +                                                       break;
>> +                                               }
>> +                                       } while ((l_iter = l_iter->next) != l_first);
>> +                               }
>> +                               else {
>>                                         ok = FALSE;
>> -                                       break;
>>                                 }
>> -                       } while ((l_iter = l_iter->next) != l_first);
>> -               }
>> -               else {
>> -                       ok = FALSE;
>> -               }
>>
>> -               if (ok) {
>> -                       BM_elem_flag_enable(f, BM_ELEM_SELECT);
>> +                               if (ok) {
>> +                                       BM_elem_flag_enable(f, BM_ELEM_SELECT);
>> +                               }
>> +                       }
>>                 }
>>         }
>>
>> @@ -810,8 +834,6 @@
>>
>>         const char flag_types[3] = {BM_VERT, BM_EDGE, BM_FACE};
>>
>> -       BMIter iter;
>> -       BMElem *ele;
>>         int i;
>>
>>         if (hflag & BM_ELEM_SELECT) {
>> @@ -825,16 +847,25 @@
>>         {
>>                 /* fast path for deselect all, avoid topology loops
>>                  * since we know all will be de-selected anyway. */
>> +
>> +#pragma omp parallel for schedule(dynamic)
>>                 for (i = 0; i < 3; i++) {
>> +                       BMIter iter;
>> +                       BMElem *ele;
>> +
>>                         ele = BM_iter_new(&iter, bm, iter_types[i], NULL);
>>                         for ( ; ele; ele = BM_iter_step(&iter)) {
>>                                 BM_elem_flag_disable(ele, BM_ELEM_SELECT);
>>                         }
>>                 }
>> +
>>                 bm->totvertsel = bm->totedgesel = bm->totfacesel = 0;
>>         }
>>         else {
>>                 for (i = 0; i < 3; i++) {
>> +                       BMIter iter;
>> +                       BMElem *ele;
>> +
>>                         if (htype & flag_types[i]) {
>>                                 ele = BM_iter_new(&iter, bm, iter_types[i], NULL);
>>                                 for ( ; ele; ele = BM_iter_step(&iter)) {
>>
>> Modified: trunk/blender/source/blender/bmesh/intern/bmesh_mesh.c
>> ===================================================================
>> --- trunk/blender/source/blender/bmesh/intern/bmesh_mesh.c      2012-12-12 04:50:53 UTC (rev 52907)
>> +++ trunk/blender/source/blender/bmesh/intern/bmesh_mesh.c      2012-12-12 05:04:01 UTC (rev 52908)
>> @@ -63,41 +63,63 @@
>>
>>  void BM_mesh_elem_toolflags_ensure(BMesh *bm)
>>  {
>> -       if (bm->toolflagpool == NULL) {
>> -               const int totflagpool_size = max_ii(512, bm->totvert + bm->totedge + bm->totface);
>> -               BLI_mempool *toolflagpool;
>> +       if (bm->vtoolflagpool && bm->etoolflagpool && bm->ftoolflagpool) {
>> +               return;
>> +       }
>>
>> -               BMIter iter;
>> -               BMElemF *ele;
>> -               const char iter_types[3] = {BM_VERTS_OF_MESH,
>> -                                           BM_EDGES_OF_MESH,
>> -                                           BM_FACES_OF_MESH};
>> +       bm->vtoolflagpool = BLI_mempool_create(sizeof(BMFlagLayer), max_ii(512, bm->totvert), 512, 0);
>> +       bm->etoolflagpool = BLI_mempool_create(sizeof(BMFlagLayer), max_ii(512, bm->totedge), 512, 0);
>> +       bm->ftoolflagpool = BLI_mempool_create(sizeof(BMFlagLayer), max_ii(512, bm->totface), 512, 0);
>>
>> -               int i;
>> -
>> -               BLI_assert(bm->totflags == 0);
>> -
>> -               /* allocate one flag pool that we don't get rid of. */
>> -               toolflagpool = BLI_mempool_create(sizeof(BMFlagLayer), totflagpool_size, 512, 0);
>> -
>> -
>> -               for (i = 0; i < 3; i++) {
>> -                       BM_ITER_MESH (ele, &iter, bm, iter_types[i]) {
>> +#pragma omp parallel sections
>> +       {
>> +#pragma omp section
>> +               {
>> +                       BLI_mempool *toolflagpool = bm->vtoolflagpool;
>> +                       BMIter iter;
>> +                       BMElemF *ele;
>> +                       BM_ITER_MESH (ele, &iter, bm, BM_VERTS_OF_MESH) {
>>                                 ele->oflags = BLI_mempool_calloc(toolflagpool);
>>                         }
>>                 }
>> +#pragma omp section
>> +               {
>> +                       BLI_mempool *toolflagpool = bm->etoolflagpool;
>> +                       BMIter iter;
>> +                       BMElemF *ele;
>> +                       BM_ITER_MESH (ele, &iter, bm, BM_EDGES_OF_MESH) {
>> +                               ele->oflags = BLI_mempool_calloc(toolflagpool);
>> +                       }
>> +               }
>> +#pragma omp section
>> +               {
>> +                       BLI_mempool *toolflagpool = bm->ftoolflagpool;
>> +                       BMIter iter;
>> +                       BMElemF *ele;
>> +                       BM_ITER_MESH (ele, &iter, bm, BM_FACES_OF_MESH) {
>>
>> @@ Diff output truncated at 10240 characters. @@
>> _______________________________________________
>> Bf-blender-cvs mailing list
>> Bf-blender-cvs at blender.org
>> http://lists.blender.org/mailman/listinfo/bf-blender-cvs
> _______________________________________________
> Bf-committers mailing list
> Bf-committers at blender.org
> http://lists.blender.org/mailman/listinfo/bf-committers

Thanks for the heads up, added BM_OMP_LIMIT so we can tweak it if its
giving issues on low poly meshes.

-- 
- Campbell


More information about the Bf-committers mailing list