c++ - 在 vector 末尾找到周期的最大频率的最快方法?

标签 c++ vector

假设我有 vector { 1, 1, 2, 1, 1, 2 } ,我想找出 vector 末尾的一个周期的最大频率。在本例中,频率 (curl) 为 2,因为 112 重复了两次。并且由于至少重复两次的任何周期最多是 vector 长度的一半,所以我只需要扫描一半的 vector 。

我正在寻找比较同一 vector 各部分的最快方法。根据最近的建议,我转而使用 std::equal(),但我不知道这是否是最好的功能,或者我是否以最快的方式使用它。

这是我目前的功能:

vector<int> sequence = someVec;
int curl = 1;
for (int length = 1; length <= sequence.size()/2); ++length) {
    int freq = 1;
    while ((freq + 1) * length <= sequence.size() and std::equal(sequence.end() - (freq + 1) * length, sequence.end() - freq * length, sequence.end() - length)) {
        ++freq;
        if (freq > curl) {
            curl = freq;
        }
    }
}

while 循环看起来确实很可怕。基本上,它会尝试在 vector 序列的末尾找到匹配的周期,如果找到重复的周期,它会检查它延长了多长时间。非常欢迎任何关于更好的实现或其他更快的编写方法的建议!!

根据要求的一些例子:

假设 vector 序列是 { 1, 1, 2, 1, 1, 2 } 它开始检查 vector 末尾有多少个 2,即1。接下来,它检查最后有多少个1, 2,即1。接下来,它检查1, 1, 2,发现这个重复 2 次。因此,旋度为 2。

假设 vector 序列是 { 2, 2, 2, 2 } 它以 2 开头并找到其中的 4 个。接下来,它检查 2, 2 并找到其中的 2 个。因此,旋度为 4。

由于我必须为长达 1 亿左右的序列找到这些 curl ,所以我真的很想从中获得最大的 yield 。 (我确实使用了一些数学近似,但是这部分程序仍然占用了大部分时间,所以我跳过了那部分)。

最佳答案

现在(因为您不再复制子 vector ),几乎所有时间都花在比较值上。

我看到有两种独立的方法可以加快速度:矢量化比较操作(如果您的编译器不这样做)和并行处理不同的长度

我实现了多线程。使用了一个包含 1,000,000 个 int 的 vector ,这是全零的“最坏情况”(因此每次比较都会运行子 vector 的全长)。单线程版本花费了将近 3 分钟,12 线程(在我的 6 核上)- 不到 30 秒。矢量化应该至少为您节省 50%(根据我过去的实验)。看到这个实现:https://community.intel.com/t5/Intel-ISA-Extensions/Q-on-memory-comparison-optimization/td-p/1041997

这是我的代码(为简单起见,我使用了全局变量):

#include <iostream>
#include <vector>
#include <mutex>
#include <thread>
#include <atomic>
#include <chrono>

// worst case scenario - all zeroes
std::vector<int> s(1'000'000);
std::mutex m_curl;
unsigned int curl = 1;
std::atomic<int> length;

unsigned int get_curl(int length)
{
  unsigned int local_curl = 1;
  unsigned int freq = 1;
  while ((freq + 1) * length <= s.size() and std::equal(s.end() - (freq + 1) * length, s.end() - freq * length, s.end() - length)) {
    ++freq;
    if (freq > local_curl) {
      local_curl = freq;
    }
  }
  return local_curl;

}

void worker()
{
  unsigned int thread_curl = 1;
  while (true)
  {
    int current_length = length.fetch_sub(1);
    if (current_length <= 0)
      break;
    int local_curl = get_curl(current_length);
    if (local_curl > thread_curl) {
      thread_curl = local_curl;
    }
  }
  // sync access to the curl
  {
    std::lock_guard<std::mutex> l(m_curl);
    if (thread_curl > curl) {
      curl = thread_curl;
    }
  }
}

int main() {
  auto t1 = std::chrono::high_resolution_clock::now();
  length = s.size() / 2;
  // create reasonable number of threads
  static const int n = std::thread::hardware_concurrency();
  std::vector<std::thread> threads;
  for (int i = 0; i < n; ++i)
    threads.emplace_back(std::thread(worker));
  // wait for all of them to finish
  for (int i = 0; i < n; ++i)
    threads[i].join();

  auto t2 = std::chrono::high_resolution_clock::now();
  std::cout << std::chrono::duration_cast<std::chrono::milliseconds>(t2 - t1).count() << std::endl;
  return curl;
}

关于c++ - 在 vector 末尾找到周期的最大频率的最快方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65010523/

相关文章:

c++ - 在 std::string 中查找第一个不是空格的字符

c++ - 应该使用 std::stof 和 atof 之间的区别是什么?

c++ - 使用一个 ifstream 变量读取多个文件

c++ - 如何从向前、向上和向右 vector 计算欧拉角?

c++ - 具有局部 y 方向的 vector 与另一个 vector 的叉积

matlab - 倍频程/Matlab : Adding new elements to a vector

c# - 从 C++ 到 C# 的 3D vector 结构

c++ - swap() 会导致未定义的行为吗?

c++ - 与使用声明在 GCC 中编译但在 MSVS 中编译的范围相同的类声明

c++ - 按每个 vector 的大小对 C++ 中的 vector vector 进行排序