线程模式搜索

时间:2014-11-10 19:21:27

标签: c++ multithreading

我正在研究一种基本上在文件中搜索模式的程序。它从1级开始,搜索文本文件中的所有不同字符。然后算法采用这些模式并使用先前模式的位置来查找新模式。它本质上是对模式的树搜索。我最近尝试线程化应用程序,我发现它实际上需要更长的时间来处理我添加到算法中的更多线程。我做了一次性能测试,并注意到我的大部分时间都花在了调用new上。新的可以包括我自己的显式调用和内部化的新调用矢量调整大小和push_backs。当我使用更多内核但是仍然可以更快地完成搜索时,即使CPU使用量也会大幅增加。似乎cpu正在努力工作,没有任何理由。我在这一点上陷入困​​境,我不知道该改变什么,但我认为另外一套眼睛对此非常有帮助。对不起,这有点模糊,不是具体问题。我没有包含TreeNode类,因为我想知道是否有人会注意到这个函数中的任何瓶颈。如果此函数中没有任何内容,我可以稍后添加其余代码。感谢

以下是有线程的代码......

void ThreadedSpanLevelTreeSearch(long level, long startPatternIndex, long numPatternsToSearch){

Timing threadTimer;
threadTimer.setTime();

string localStream = fileStreamBuffer.str();
vector<TreeNode*> localTree;
TreeNode *leaf;
for(int i = startPatternIndex; i < numPatternsToSearch + startPatternIndex; i++)
{
    //countMutex->lock();
    //computationCount++;
    //countMutex->unlock();

    leaf = prevVectorizedTree[i];
    if(leaf != NULL)
    {
        vector<long> pList = leaf->GetPList();
        long pListLength = leaf->GetPListCount();

        for(int k = 0; k < pListLength; k++)
        {
            //If pattern is past end of string stream then stop counting this pattern
            if(pList[k] < localStream.size())
            {
                unsigned char value = localStream[pList[k]];
                //
                switch(currPattern)
                {
                    case PATTERNTYPE::NUMBERS:
                    {
                        if(value >= 48 && value <= 57)
                        {
                            leaf->addLeaf(value, level, pList[k]+1);
                        }
                        break;
                    }
                    case PATTERNTYPE::ALPHABET:
                    {
                        if((value >= 32 && value <= 126))
                        {
                            leaf->addLeaf(value, level, pList[k]+1);
                        }
                        break;
                    }
                    case PATTERNTYPE::EVERYTHING:
                    {
                        leaf->addLeaf(value, level, pList[k]+1);
                        break;
                    }
                    default:
                    {
                        break;
                    }
                };

            }
        }

        for(int z = 0; z < patternArrayLength; z++)
        {
            if(leaf->GetLeaf(patternArray[z]) != NULL)
            {

                if(leaf->GetLeaf(patternArray[z])->GetPListCount() > 1)
                {
                    localTree.push_back(leaf->GetLeaf(patternArray[z]));
                }
                //deallocate
                else if(leaf->GetLeaf(patternArray[z])->GetPListCount() <= 1)
                {
                    delete leaf->GetLeaf(patternArray[z]);
                }
            }
        }   
    }
    delete leaf;
}
countMutex->lock();
globalVectorizedTree.insert(globalVectorizedTree.end(), localTree.begin(), localTree.end());
countMutex->unlock();

//cout << "thread " << ceil(startPatternIndex/numPatternsToSearch) << " finished" << endl;
//cout << "time taken for core: " << threadTimer.getTime() << endl;

}

1 个答案:

答案 0 :(得分:0)

不同线程分配资源的池是相同的。它受到并发访问的保护,但是从不同的线程使用它会导致这些数据在不同的CPU缓存之间来回绑定,这会降低性能。

有一些事情需要改变:

  • 避免不必要的分配。除非确实需要,否则请避免动态分配此外,在几乎所有情况下,简单数组或向量的性能都优于链表,它们往往在Big-O表示法中具有较大的n_0
  • 避免复制。例如,不应要求localStream pList
  • 避免不必要的重新分配,例如对于向量使用reserve()。有一点,分配太多的开销超过了复制的开销。这一点还取决于程序中的一般用法。
  • 您可以使用使用特定于线程的池的分配器。
  • 避免无用地启动线程。如果每个线程的工作量很小,则启动和关闭时间可能占主导地位。在某些情况下,使用线程池可能有所帮助。