की तुलना में बहुत धीमी गति से काम करता है मेरे पास एक perf परीक्षण फ़ंक्शन का .NET और C++ कार्यान्वयन है जो 6838 कुंजी के पूल से स्ट्रिंग कुंजियों का उपयोग करके एक शब्दकोश में 854,750 लुकअप करता है। मैंने इन कार्यों को एक असली ऐप में एक पेर्फ बाधा की जांच करने के लिए लिखा था।स्ट्रिंग कुंजी के साथ unordered_map में सी ++ ~ 1 एम लुक-अप .NET कोड
नेट कार्यान्वयन, एफ # में लिखा है शब्दकोश का उपयोग करता है और .NET 4.0
सी ++ कार्यान्वयन के लिए संकलित किया गया है std :: unordered_map उपयोग करता है और रिलीज मोड में VS2010 के साथ बनाया गया है।
मेरी मशीन पर .NET कोड औसतन 240 एमएस में चलता है और सी ++ कोड 630 एमएस में चलता है। क्या आप कृपया समझने में मेरी मदद कर सकते हैं कि गति में इस विशाल अंतर का क्या कारण हो सकता है?
यदि मैं सी ++ कार्यान्वयन छोटा में महत्वपूर्ण लंबाई बनाता हूं और "key_prefix_" के बजाय "key_" उपसर्ग का उपयोग करता हूं तो यह 140 एमएस में चलाएगा।
एक और चाल मैंने कोशिश की है कि एक कस्टम अपरिवर्तनीय स्ट्रिंग कार्यान्वयन के साथ std :: स्ट्रिंग को प्रतिस्थापित करना है जिसमें स्रोत के लिए एक कॉन्स char * सूचक और एक बार गणना की हैश है। इस स्ट्रिंग का उपयोग सी ++ कार्यान्वयन के प्रदर्शन को 190 एमएस तक कम करने की अनुमति है।
सी ++ कोड:
struct SomeData
{
public:
float Value;
};
typedef std::string KeyString;
typedef std::unordered_map<KeyString, SomeData> DictionaryT;
const int MaxNumberOfRuns = 125;
const int MaxNumberOfKeys = 6838;
DictionaryT dictionary;
dictionary.rehash(MaxNumberOfKeys);
auto timer = Stopwatch::StartNew();
int lookupCount = 0;
char keyBuffer[100] = "key_prefix_";
size_t keyPrefixLen = std::strlen(keyBuffer);
/// run MaxNumberOfRuns * MaxNumberOfKeys iterations
for(int runId = 0; runId < MaxNumberOfRuns; runId++)
{
for(int keyId = 0; keyId < MaxNumberOfKeys; keyId++)
{
/// get a new key from the pool of MaxNumberOfKeys keys
int randomKeySuffix = (std::rand() % MaxNumberOfKeys);
::itoa(randomKeySuffix, keyBuffer + keyPrefixLen, 10);
KeyString key = keyBuffer;
/// lookup key in the dictionary
auto dataIter = dictionary.find(key);
SomeData* data;
if(dataIter != dictionary.end())
{
/// get existing value
data = &dataIter->second;
}
else
{
/// add a new value
data = &dictionary.insert(dataIter, DictionaryT::value_type(key, SomeData()))->second;
}
/// update corresponding value in the dictionary
data->Value += keyId * runId;
lookupCount++;
}
}
timer.Stop();
std::cout << "Time: " << timer.GetElapsedMilleseconds() << " ms" << std::endl;
std::cout << "Lookup count: " << lookupCount << std::endl;
प्रिंटों:
समय: 636 एमएस
लुक गिनती: 854750
एफ # कोड
open System
open System.Diagnostics
open System.Collections.Generic
type SomeData =
struct
val mutable Value : float
end
let dictionary = new Dictionary<string, SomeData>()
let randomGen = new Random()
let MaxNumberOfRuns = 125
let MaxNumberOfKeys = 6838
let timer = Stopwatch.StartNew()
let mutable lookupCount = 0
/// run MaxNumberOfRuns * MaxNumberOfKeys iterations
for runId in 1 .. MaxNumberOfRuns do
for keyId in 1 .. MaxNumberOfKeys do
/// get a new key from the pool of MaxNumberOfKeys keys
let randomKeySuffix = randomGen.Next(0, MaxNumberOfKeys).ToString()
let key = "key_prefix_" + randomKeySuffix
/// lookup key in the dictionary
let mutable found, someData = dictionary.TryGetValue (key)
if not(found) then
/// add a new value
someData <- new SomeData()
dictionary.[key] <- someData
/// update corresponding value in the dictionary
someData.Value <- someData.Value + float(keyId) * float(runId)
lookupCount <- lookupCount + 1
timer.Stop()
printfn "Time: %d ms" timer.ElapsedMilliseconds
printfn "Lookup count: %d" lookupCount
प्रिंटों:
समय: 245 एमएस
लुक गिनती: 854750
शायद unordered_map end iterator का उपयोग करते हुए अगले तत्व संकेत प्रदर्शन में बाधा डाल रहा है? – GWW
दोनों ठंडे कैश या दोनों गर्म कैश से चलते हैं? – sarnold
कोई भी तत्व अगले संकेत संकेत को हटाने में मदद नहीं करता है :(दोनों कार्य ठंडे कैश के साथ चलते हैं। – evgenyp