[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