क्या मैं std :: एक समानांतर निष्पादन नीति के साथ जगह में परिवर्तन कर सकता हूँ?


11

अगर मैं गलत नहीं हूँ, मैं कर सकते हैं std::transformप्रदर्शन जगह में एक इनपुट और आउटपुट इटरेटर के समान सीमा का उपयोग करके। मान लें कि मेरे पास कुछ std::vectorवस्तु है vec, तो मैं लिखूंगा

std::transform(vec.cbegin(),vec.cend(),vec.begin(),unary_op)

एक उपयुक्त एकरी संचालन का उपयोग करना unary_op

सी ++ 17 मानक का उपयोग करते हुए, मैं std::execution::parपहले तर्क के रूप में एक में चिपकाकर समानांतर में परिवर्तन को निष्पादित करना चाहूंगा । यह फ़ंक्शन को अधिभार लेखstd::transform में अधिभार (1) से (2) तक जाने देगा । हालाँकि इस अधिभार की टिप्पणी कहती है:

unary_op[...] अंत पुनरावृत्तियों सहित किसी भी पुनरावृत्तियों को अमान्य नहीं करना चाहिए, या इसमें शामिल श्रेणियों के किसी भी तत्व को संशोधित करना चाहिए। (सी ++ 11 के बाद से)

क्या "किसी भी तत्व को संशोधित करता है" वास्तव में इसका मतलब है कि मैं एल्गोरिथ्म का उपयोग नहीं कर सकता हूं या क्या यह एक अलग विवरण के बारे में बात कर रहा है जिसे मैंने गलत समझा है?

जवाबों:


4

यहाँ मानक को उद्धृत करने के लिए

[Alg.transform.1]

op [...] पुनरावृत्तियों या सबरेंज को अमान्य नहीं करेगा, या श्रेणियों में तत्वों को संशोधित नहीं करेगा

यह आपके unary_opतर्क या कंटेनर के रूप में दिए गए मान को संशोधित करने के लिए मना करता है।

auto unary_op = [](auto& value) 
{ 
    value = 10;    // this is bad
    return value;
}

auto unary_op = [&vec](auto const& value) 
{ 
    vec[0] = value;   // also bad
    return value;
}

auto unary_op = [&vec](auto& value) 
{ 
    vec.erase(vec.begin());   // nope 
    return value;
}

हालांकि, follwing ठीक है।

auto unary_op = [](auto& value)  // const/ref not strictly needed
{         
    return value + 10;   // totally fine
}

auto unary_op = [&vec](auto& value)
{         
    return value + vec[0];   // ok in sequential but not in parallel execution
}

UnaryOperationहमारे पास से स्वतंत्र है

[Alg.transform.5]

परिणाम एकात्मक परिवर्तन [...] के मामले में पहले के बराबर हो सकता है।

अर्थ-इन-प्लेस ऑपरेशन स्पष्ट रूप से अनुमत हैं।

अभी

[Algorithms.parallel.overloads.2]

जब तक अन्यथा निर्दिष्ट नहीं किया जाता है, ExecutionPolicy एल्गोरिथ्म ओवरलोड के शब्दार्थ बिना उनके ओवरलोड के समान हैं।

इसका मतलब है कि निष्पादन नीति का एल्गोरिदम पर कोई उपयोगकर्ता दृश्यमान अंतर नहीं है। आप उम्मीद कर सकते हैं कि एल्गोरिथ्म ठीक उसी परिणाम का उत्पादन करेगा जैसे आप एक निष्पादन नीति को निर्दिष्ट नहीं करेंगे।


6

मेरा मानना ​​है कि यह एक अलग विस्तार के बारे में बात कर रहा है। unary_opअनुक्रम का एक तत्व लेता है और एक मान देता है। वह मान transformगंतव्य क्रम में संग्रहीत (द्वारा ) है।

तो यह unary_opठीक होगा:

int times2(int v) { return 2*v; }

लेकिन यह एक नहीं होगा:

int times2(int &v) { return v*=2; }

लेकिन यह वास्तव में आप के बारे में क्या पूछ रहे हैं नहीं है। आप जानना चाहते हैं कि क्या आप समान स्रोत और गंतव्य श्रेणी के साथ समानांतर एल्गोरिदम के unary_opसंस्करण का उपयोग कर सकते हैं transform। मैं नहीं देखता क्यों नहीं। transformगंतव्य अनुक्रम के एक तत्व के लिए स्रोत अनुक्रम का एक तत्व मैप करता है। हालांकि, यदि आपकी unary_opवास्तव में एकात्मकता नहीं है, (यानी, यह अनुक्रम में अन्य तत्वों को संदर्भित करता है - भले ही यह केवल उन्हें पढ़ता है, तो आपके पास डेटा दौड़ होगी)।


1

जैसा कि आप उद्धृत लिंक के उदाहरण में देख सकते हैं, किसी भी तत्व को संशोधित करने का मतलब यह नहीं है कि तत्वों पर सभी प्रकार के संशोधन हैं:

फ़ंक्शन का हस्ताक्षर निम्नलिखित के बराबर होना चाहिए:

Ret fun(const Type &a);

इसमें तत्वों पर संशोधन शामिल है। सबसे खराब स्थिति में यदि आप गंतव्य के लिए एक ही पुनरावृत्ति का उपयोग करते हैं, तो संशोधन में पुनरावृत्तियों के अमान्यकरण का कारण नहीं होना चाहिए, जैसे कि push_backसदिश या erasइंग के लिए vectorजो संभवतः पुनरावृत्तियों के अमान्य होने का कारण होगा।

विफलता का एक उदाहरण देखें जिसे आप लाइव नहीं करेंगे ।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.