diff --git a/PyModules/skin_plus_plus/skin_plus_plus_pymxs/src/SkinPlusPlusPymxs/SkinPlusPlusPymxs.cpp b/PyModules/skin_plus_plus/skin_plus_plus_pymxs/src/SkinPlusPlusPymxs/SkinPlusPlusPymxs.cpp index cc3c749..f8ac9bd 100644 --- a/PyModules/skin_plus_plus/skin_plus_plus_pymxs/src/SkinPlusPlusPymxs/SkinPlusPlusPymxs.cpp +++ b/PyModules/skin_plus_plus/skin_plus_plus_pymxs/src/SkinPlusPlusPymxs/SkinPlusPlusPymxs.cpp @@ -88,18 +88,18 @@ std::vector>> SkinData::getSkinWeights() //SkinArray skinDataArray(2, VertexArray(vertexCount)); for (unsigned int vertexIndex = 0; vertexIndex < vertexCount; vertexIndex++) { - int16_t influenceCount = this->iSkinContextData->GetNumAssignedBones(vertexIndex); + auto influenceCount = this->iSkinContextData->GetNumAssignedBones(vertexIndex); std::vector influenceWeights(influenceCount); std::vector influenceBoneIDs(influenceCount); //influenceWeights[0] = 1.0f; //influenceWeights->data()[0] = 1.0f; skinDataArray[0][vertexIndex] = influenceWeights; //influenceWeights skinDataArray[1][vertexIndex] = influenceBoneIDs; //influenceBoneIDs - for (int influenceIndex = 0; influenceIndex < influenceCount; influenceIndex++) + for (auto influenceIndex = 0; influenceIndex < influenceCount; influenceIndex++) { - float infuenceWeight = this->iSkinContextData->GetBoneWeight(vertexIndex, influenceIndex); + auto infuenceWeight = this->iSkinContextData->GetBoneWeight(vertexIndex, influenceIndex); if (infuenceWeight <= 0.0f) continue; - int influenceBoneID = this->iSkinContextData->GetAssignedBone(vertexIndex, influenceIndex); + auto influenceBoneID = this->iSkinContextData->GetAssignedBone(vertexIndex, influenceIndex); influenceWeights[influenceIndex] = infuenceWeight; influenceBoneIDs[influenceIndex] = float(influenceBoneID); } @@ -174,41 +174,33 @@ PYBIND11_MODULE(SkinPlusPlusPymxs, m) { .def("initialise", &SkinData::initialise) .def("get_skin_weights", &SkinData::getSkinWeightsPy) ; - - m.def("get_skin_weights", [&](wchar_t* name) { + //def("__init__", [](...) { ... }, py::arg().noconvert(), py::arg("arg2") = false); + m.def("get_skin_weights", [](wchar_t* name, int return_type) { std::vector>> weights = getSkinWeights(name); - return py::cast(weights); + switch (return_type) { + case 0: + return py::cast(weights); + case 1: + return py::cast(weights, py::return_value_policy::take_ownership); + case 2: + return py::cast(weights, py::return_value_policy::copy); + case 3: + return py::cast(weights, py::return_value_policy::move); + case 4: + return py::cast(weights, py::return_value_policy::reference); + case 5: + return py::cast(weights, py::return_value_policy::reference_internal); + case 6: + return py::cast(weights, py::return_value_policy::automatic); + case 7: + return py::cast(weights, py::return_value_policy::automatic_reference); + default: + return py::cast(weights); + } + }, "Get Skin Weights", - py::arg("name") - ); - m.def( - "get_skin_weights_np", [&](wchar_t* name) { - std::vector>> weights = getSkinWeights(name); - py::array npArray = py::cast(weights); - return npArray; - }, "Get Skin Weights as a numpy array", - py::arg("name") - ); - m.def("get_skin_weights_np_move", [&](wchar_t* name) { - std::vector>> weights = getSkinWeights(name); - py::array npArray = py::cast(weights, py::return_value_policy::move); - return npArray; - }, "Get Skin Weights as a numpy array", - py::arg("name") - ); - m.def("get_skin_weights_np_take_ownership", [&](wchar_t* name) { - std::vector>> weights = getSkinWeights(name); - py::array npArray = py::cast(weights, py::return_value_policy::take_ownership); - return npArray; - }, "Get Skin Weights as a numpy array", - py::arg("name") - ); - m.def("get_skin_weights_np_take_ownership", [&](wchar_t* name) { - std::vector>> weights = getSkinWeights(name); - py::array npArray = py::cast(weights, py::return_value_policy::take_ownership); - return npArray; - }, "Get Skin Weights as a numpy array", - py::arg("name") + py::arg("name"), + py::arg("return_type") ); //m.def("f", []() { // // Allocate and initialize some data; make this big so diff --git a/test/test.py b/test/test.py index 4ee3658..bc57432 100644 --- a/test/test.py +++ b/test/test.py @@ -1,5 +1,6 @@ from __future__ import annotations +import numpy as np import functools import pathlib import time @@ -29,10 +30,10 @@ import SkinPlusPlusPymxs -skin_data = SkinPlusPlusPymxs.SkinData() -skin_data.initialise("Sphere001") -skin_weights = skin_data.getSkinWeights() -print(skin_weights[0][1]) +# skin_data = SkinPlusPlusPymxs.SkinData() +# skin_data.initialise("Sphere001") +# skin_weights = skin_data.getSkinWeights() +# print(skin_weights[0][1]) __loops__ = 1 @@ -45,7 +46,7 @@ def get_loops(): return __loops__ -def timer(data_dict: dict[str, tuple[float, Any]]) -> Callable: +def timer(data_dict: dict[str, tuple[float, Any, str]]) -> Callable: def wrapper(function: Callable) -> Callable: @functools.wraps(function) def wrapper_timer(*args, **kwargs) -> Any: @@ -54,7 +55,7 @@ def wrapper_timer(*args, **kwargs) -> Any: for _ in range(get_loops()): value = function(*args, **kwargs) run_time = time.perf_counter() - start_time - data_dict[f"{function.__name__!r}"] = (run_time, value) + data_dict[f"{function.__name__!r}"] = (run_time, value, function.__name__) return value return wrapper_timer return wrapper @@ -91,7 +92,7 @@ def SetSkinWeights(node, boneIDs, weights) -> None: ReplaceVertexWeights(skinModifier, vertexIndex, boneIDs[vertexIndex], weights[vertexIndex]) -get_timer_dict: dict[str, tuple[float, Any]] = {} +get_timer_dict: dict[str, tuple[float, Any, str]] = {} @timer(get_timer_dict) def mxs_GetSkinWeights(_obj): data = mxsGetSkinWeights(_obj) @@ -100,6 +101,15 @@ def mxs_GetSkinWeights(_obj): return weights, boneIDs +@timer(get_timer_dict) +def mxs_GetSkinWeights_NP(_obj): + data = mxsGetSkinWeights(_obj) + + weights = np.array([np.array(list(weights), dtype=float) for weights in data[0]], dtype=float) + boneIDs = np.array([np.array(list(boneIDs), dtype=float) for boneIDs in data[1]], dtype=float) + # boneIDs = [list(boneIDs) for boneIDs in data[1]] + + return weights, boneIDs @timer(get_timer_dict) def pymxs_GetSkinWeights(_obj): @@ -132,26 +142,37 @@ def cpppf_GetSkinWeights(_obj): @timer(get_timer_dict) def pybind11_GetSkinWeights(_obj): - - return SkinPlusPlusPymxs.get_skin_weights(_obj.Name) + return SkinPlusPlusPymxs.get_skin_weights(_obj.Name, 0) @timer(get_timer_dict) -def pybind11np_GetSkinWeights(_obj): +def pybind11_GetSkinWeights_take_ownership(_obj): + return SkinPlusPlusPymxs.get_skin_weights(_obj.Name, 1) - return SkinPlusPlusPymxs.get_skin_weights_np(_obj.Name) +@timer(get_timer_dict) +def pybind11_GetSkinWeights_copy(_obj): + return SkinPlusPlusPymxs.get_skin_weights(_obj.Name, 2) @timer(get_timer_dict) -def pybind11npmove_GetSkinWeights(_obj): +def pybind11_GetSkinWeights_move(_obj): + return SkinPlusPlusPymxs.get_skin_weights(_obj.Name, 3) - return SkinPlusPlusPymxs.get_skin_weights_np_move(_obj.Name) +@timer(get_timer_dict) +def pybind11_GetSkinWeights_reference(_obj): + return SkinPlusPlusPymxs.get_skin_weights(_obj.Name, 4) @timer(get_timer_dict) -def pybind11nptakeownership_GetSkinWeights(_obj): +def pybind11_GetSkinWeights_reference_internal(_obj): + return SkinPlusPlusPymxs.get_skin_weights(_obj.Name, 5) - return SkinPlusPlusPymxs.get_skin_weights_np_take_ownership(_obj.Name) +@timer(get_timer_dict) +def pybind11_GetSkinWeights_automatic(_obj): + return SkinPlusPlusPymxs.get_skin_weights(_obj.Name, 6) +@timer(get_timer_dict) +def pybind11_GetSkinWeights_automatic_reference(_obj): + return SkinPlusPlusPymxs.get_skin_weights(_obj.Name, 7) -set_timer_dict: dict[str, tuple[float, Any]] = {} +set_timer_dict: dict[str, tuple[float, Any, str]] = {} @timer(set_timer_dict) def mxs_SetSkinWeights( _obj, _boneIDs, _weights): return SetSkinWeights(_obj, _boneIDs, _weights) @@ -172,26 +193,22 @@ def cpppf_SetSkinWeights( _obj, _boneIDs, _weights): obj = mxRt.GetNodeByName("Sphere001") get_function_list = ( - # pymxs_GetSkinWeights, - # mxs_GetSkinWeights, - # cppfp_GetSkinWeights, - # cpppm_GetSkinWeights, - # cpppf_GetSkinWeights, + pymxs_GetSkinWeights, + mxs_GetSkinWeights, + mxs_GetSkinWeights_NP, + cppfp_GetSkinWeights, + cpppm_GetSkinWeights, + cpppf_GetSkinWeights, pybind11_GetSkinWeights, - pybind11np_GetSkinWeights, - pybind11npmove_GetSkinWeights, - pybind11nptakeownership_GetSkinWeights, - # lambda: pybind11np_GetSkinWeights(obj), + pybind11_GetSkinWeights_take_ownership, + pybind11_GetSkinWeights_copy, + pybind11_GetSkinWeights_move, + pybind11_GetSkinWeights_reference, + pybind11_GetSkinWeights_reference_internal, + pybind11_GetSkinWeights_automatic, + pybind11_GetSkinWeights_automatic_reference, ) -# weights = [(0.5, 0.5) for _ in range(obj.Verts.Count)] -# ids = [(1, 2) for _ in range(obj.Verts.Count)] -# set_function_list = ( -# lambda: mxs_SetSkinWeights(obj, weights, ids), -# lambda: cppfp_SetSkinWeights(obj, weights, ids), -# lambda: cpppm_SetSkinWeights(obj, weights, ids), -# lambda: cpppf_SetSkinWeights(obj, weights, ids), -# ) set_loops(1) def run_functions(function_list, _obj): @@ -202,15 +219,15 @@ def run_functions(function_list, _obj): print(type(result)) print(len(result)) -def process_results(time_data: dict[str, tuple[float, Any]]): - times = [] - values = [] - for time, value in time_data.values(): - times.append(time) - values.append(value) - - max_time = max(times) - for function_name, (time, value) in time_data.items(): +def process_results(time_data: "dict[str, tuple[float, Any, str]]"): + # times = [] + # values = [] + data = list(time_data.values()) + data.sort(key=lambda x: x[0]) + max_time = data[-1][0] + data.reverse() + # max_time = max(times) + for time, _, function_name in data: percentage_ratio = (max_time / time) message = f"{function_name}: {time} -" if percentage_ratio == 1.0: @@ -223,4 +240,20 @@ def process_results(time_data: dict[str, tuple[float, Any]]): run_functions(get_function_list, obj) process_results(get_timer_dict) -# print(np_GetSkinWeights()) + +| Function | Time-secs | x Faster | % Faster | +|---------------------------------------------|---------------------|----------------------|----------------------| +| pymxs_GetSkinWeights | 20.34769090000009 | base line | base line | +| mxs_GetSkinWeights_NP | 15.51825759999997 | 1.3112097649416599 x | 131.12097649416597 % | +| mxs_GetSkinWeights | 14.42323169999986 | 1.4107580966060669 x | 141.0758096606067 % | +| cpppf_GetSkinWeights | 7.435437399999955 | 2.7365829076847867 x | 273.65829076847865 % | +| cppfp_GetSkinWeights | 6.338866400000143 | 3.2099889185232917 x | 320.99889185232917 % | +| cpppm_GetSkinWeights | 5.98266609999996 | 3.4011075597216136 x | 340.11075597216137 % | +| pybind11_GetSkinWeights_automatic | 1.2681291999999758 | 16.045439928360988 x | 1604.5439928360988 % | +| pybind11_GetSkinWeights_move | 1.09791139999993 | 18.533090101807293 x | 1853.3090101807293 % | +| pybind11_GetSkinWeights_copy | 0.9864563000000999 | 20.627057579740764 x | 2062.7057579740763 % | +| pybind11_GetSkinWeights | 0.9028401000000486 | 22.537424844110262 x | 2253.7424844110265 % | +| pybind11_GetSkinWeights_reference_internal | 0.4243109000001368 | 47.954674037347445 x | 4795.467403734745 % | +| pybind11_GetSkinWeights_automatic_reference | 0.4236172999999326 | 48.03319151508526 x | 4803.3191515085255 % | +| pybind11_GetSkinWeights_take_ownership | 0.41753419999986363 | 48.73299217167536 x | 4873.299217167536 % | +| pybind11_GetSkinWeights_reference | 0.41740709999999126 | 48.747831313843285 x | 4874.783131384329 % |