C++ 在向量末尾找到周期最大频率的最快方法?

C++ 在向量末尾找到周期最大频率的最快方法?,c++,vector,C++,Vector,假设我有向量{1,1,2,1,1,2},我想找出向量末尾的一个周期的最大频率。在这种情况下,频率(curl)为2,因为112重复两次。因为任何周期重复至少两次,最多是向量长度的一半,我只需要扫描向量的一半 我正在寻找比较同一向量各部分的最快方法。根据最近的建议,我使用了std::equal(),但我不知道这是不是最好的函数,或者我是否以最快的方式使用它 这是我目前的职能: vector<int> sequence = someVec; int curl = 1; for (int l

假设我有向量
{1,1,2,1,1,2}
,我想找出向量末尾的一个周期的最大频率。在这种情况下,频率(curl)为2,因为
112
重复两次。因为任何周期重复至少两次,最多是向量长度的一半,我只需要扫描向量的一半

我正在寻找比较同一向量各部分的最快方法。根据最近的建议,我使用了
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;
        }
    }
}
向量序列=someVec;
int curl=1;
对于(int length=1;length现在(因为您不再复制子向量),几乎所有的时间都花在比较值上

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

我实现了多线程。使用了一个1000000
int
s的向量,这个“最坏情况”是全零(因此每次比较都会运行子向量的整个长度)。一个单线程版本花费了将近3分钟,12个线程(在我的6核上)不到30秒。向量化至少可以为您节省50%(基于我过去的实验)。有关实施情况,请参见:

以下是我的代码(为了简单起见,我使用了globals):

#包括
#包括
#包括
#包括
#包括
#包括
//最坏情况-全零
标准:向量s(1'000'000);
std::互斥m_curl;
无符号整数旋度=1;
std:原子长度;
无符号整数get_curl(整数长度)
{
无符号int局部_curl=1;
无符号整数频率=1;
而((频率+1)*长度局部卷曲){
局部旋度=频率;
}
}
返回局部卷曲;
}
void worker()
{
无符号整数线程\u curl=1;
while(true)
{
int current_length=length.fetch_sub(1);
if(当前螺纹长度螺纹卷曲度){
螺纹旋度=局部旋度;
}
}
//同步对卷的访问
{
标准:锁紧护罩l(m_卷曲);
if(螺纹卷曲>卷曲){
卷曲度=螺纹卷曲度;
}
}
}
int main(){
自动t1=std::chrono::高分辨率时钟::现在();
长度=s.尺寸()/2;
//创建合理数量的线程
静态常量int n=std::thread::hardware_concurrency();
向量线程;
对于(int i=0;istd::cout您的描述不清楚。请添加一个输入/输出示例。最终答案是使用您的代码编写一个测试,使用
std::equal
编写另一个测试。启动优化器并开始计时。如果您仔细阅读他们的问题要求并调整问题以匹配,您可能有理由。是的,我链接到了如何询问pag实际上,请不要在两个网站上交叉张贴问题。你的问题似乎在这里的主题上,但你需要做一些更改。首先,从问题描述开始,然后展示你的尝试。另外,停止寻找尾随子向量的确切逻辑是什么?我想我可以弄清楚,但你应该解释一下不用担心,不用着急:)如果你的问题被解决了,我们仍然会在修复后重新打开它。太棒了!我想知道,你为
矢量化
改变了什么部分?因为在我的一种脚本中,我已经使用了多线程,因为我在同一时间做了大量较小的序列,所以它们不会从多线程中获益。(明天我将对此脚本进行一些测试)@StevenCellist-我刚刚在我的答案中添加了一个链接。您将使用向量化的
memcmp
替换
std::equal
。还要注意,我已经实现了一个线程池,因此每个线程都得到了最大限度的利用。您认为多线程中的多线程仍然会获得优势吗?(顺便说一句,我有更多的问题,我觉得这些问题不适合这里。如果你不介意的话,我们可以私下谈谈吗?@StevenCellist-拥有比你的硬件能够处理的更多的线程是没有意义的。但是要100%地使用你的CPU,你至少需要有这么多:)这个特定任务对向量进行只读访问,因此没有争用,等待互斥,等等。我尝试(第一次)在这里创建一个聊天室:让我们看看它是否有效,否则我们将找到另一种方法
#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;
}