C ++优化

时间:2017-10-17 06:45:28

标签: c++ optimization

我正在做一些实时的东西,我需要很快的速度。但在我的代码中,我有这个:

float maxdepth;
uint32_t faceindex;

for (uint32_t tr_iterator = 0; tr_iterator < facesNum-1; tr_iterator++)
{
    maxdepth = VXTrisDepth[tr_iterator];
    faceindex = tr_iterator;
    uint32_t tr_literator = 3*tr_iterator;
    uint32_t facelindex = 3*faceindex;
    for (uint32_t tr_titerator = tr_iterator+1; tr_titerator < facesNum; tr_titerator++)
    {
        float depth = VXTrisDepth[tr_titerator];
        if (depth > maxdepth)
        {
            maxdepth = depth;
            faceindex = tr_titerator;
        }
    }
    Vei2 itmpx = trs[tr_literator+0];
    trs[tr_literator+0] = trs[facelindex+0];
    trs[facelindex+0] = itmpx;
         itmpx = trs[tr_literator+1];
    trs[tr_literator+1] = trs[facelindex+1];
    trs[facelindex+1] = itmpx;
         itmpx = trs[tr_literator+2];
    trs[tr_literator+2] = trs[facelindex+2];
    trs[facelindex+2] = itmpx;
    float id   = VXTrisDepth[tr_iterator];
    VXTrisDepth[tr_iterator] = VXTrisDepth[faceindex];
    VXTrisDepth[faceindex] = id;
}

VXTrisDepth只是一个float数组,faceindex是一个uint32_t并且是一个大数字,trs是一个Vei2数组,而Vei2只是一个整数2D向量。 问题是,当我们在facenum中有16074这样的东西时,这个循环需要700毫秒才能在我的计算机上运行,​​这太过分了,还有任何优化的想法吗?

1 个答案:

答案 0 :(得分:0)

我已经重写了一下,以了解你到底在做什么。

警告所有代码 未经测试

float maxdepth;
uint32_t faceindex;

for (uint32_t tr_iterator = 0; tr_iterator < facesNum-1; tr_iterator++) {
    faceindex = tr_iterator;
    uint32_t tr_literator = 3*tr_iterator;
    uint32_t facelindex = 3*faceindex;

    auto fi = std::max_element(&VXTrisDepth[tr_iterator], &VXTrisDepth[facesNum]);
    maxdepth = *fi;
    faceindex = std::distance(&VXTrisDepth[0], fi);

    // hmm was this originally a VEC3...
    std::swap(trs[tr_literator+0], trs[facelindex+0]);
    std::swap(trs[tr_literator+1], trs[facelindex+1]);
    std::swap(trs[tr_literator+2], trs[facelindex+2]);

    // with the above this looks like a struct of arrays. SOA vs AOS
    std::swap(VXTrisDepth[tr_iterator], VXTrisDepth[faceindex]);
}

现在它看起来像两个数组的selection sort是O(N ^ 2),难怪它感觉很慢。

有多种方法可以对此进行排序

  • 外部索引,创建一个长度为facesNum的数组,从零到facesNum-1初始化,并使用索引将它们排序到VXTrisDepth。然后根据索引数组重新排序2个原始数组。
  • 外部索引和键对,使其易于使用std :: pair,对其进行排序,然后重新排序原始的2个数组。
  • 对2个数组进行排序,好像它是一个,轻微的黑客攻击。使用std :: swap你需要专注于一个类型,所以它可能被误用来交换2个数组。无需额外存储空间。

让我们尝试使用外部对的简易版本。

我们需要3个阶段

  • 制作辅助数组O(N)
  • 排序辅助数组O(N lg N)
  • 重新排序原始数组O(N)

还有一些代码

// make helper array
using hPair = std::pair<float, int>; // order is important
std::vector<hPair> helper;
helper.reserve(numFaces);

for (int idx = 0; idx < facesNum; idx++)
  helper.emplace_back(VXTrisDepth[idx], idx);

// sort it using std::pair's operator < or write your own
std::sort(helper.begin(), helper.end());

// reorder the SOA arrays
auto vx = std::begin(VXTrisDepth);
for (auto& help : helper) {
  int tr_literator = help.second;
  std::swap(trs[tr_literator+0], trs[facelindex+0]);
  std::swap(trs[tr_literator+1], trs[facelindex+1]);
  std::swap(trs[tr_literator+2], trs[facelindex+2]);

  *vs++ = help.first; // we already have the sorted depth in helper.
  //std::swap(VXTrisDepth[tr_iterator], VXTrisDepth[faceindex]);
}    

请记住测试它仍然有效......你已经有一个测试框架吗?