আমি কী সমান্তরাল এক্সিকিউশন পলিসির সাথে জায়গায় std :: রূপান্তর ব্যবহার করতে পারি?


11

যদি আমার ভুল না হয় তবে আমি ইনপুট এবং আউটপুট পুনরুক্তি হিসাবে একই পরিসীমা ব্যবহার করে জায়গায়std::transform সঞ্চালনা করতে পারি । ধরুন আমার কিছু বস্তু আছে , তবে আমি লিখবstd::vectorvec

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

একটি উপযুক্ত unary অপারেশন ব্যবহার করে unary_op

C ++ 17 স্ট্যান্ডার্ড ব্যবহার করে, আমি std::execution::parপ্রথম যুক্তি হিসাবে সেখানে একটি আটকে সমান্তরালে রূপান্তরটি সম্পাদন করতে চাই । এটি ফাংশনটিকে ওভারলোড (1) থেকে (2) এ সিপ্রেফারেন্স নিবন্ধে যেতে দেয়std::transform । তবে এই ওভারলোডের মন্তব্যগুলি বলে:

unary_op[...] অবশ্যই শেষ পুনরাবৃত্তকারীগুলি সহ কোনও পুনরাবৃত্তিকারীকে অবৈধ করতে হবে না, বা জড়িত ব্যাপ্তির কোনও উপাদানকে সংশোধন করবে না। (যেহেতু সি ++ 11)

"কোনও উপাদানকে সংশোধন করুন" এর অর্থ কি আসলে আমি অ্যালগরিদমটি জায়গায় ব্যবহার করতে পারি না বা এটি কি অন্যরকম বিস্তারিত সম্পর্কে কথা বলছে যা আমি ভুল ব্যাখ্যা করেছি?

উত্তর:


4

এখানে মান উদ্ধৃত

[Alg.transform.1]

ওপ [...] পুনরাবৃত্তকারী বা উপশ্রেণীকে অবৈধ করবে না, বা রেঞ্জগুলিতে উপাদানগুলি সংশোধন করবে না

এটি 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;
}

তবে, ফলউইং ঠিক আছে।

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]

অন্যথায় নির্দিষ্ট না করা হলে এক্সিকিউশনপলিসি অ্যালগরিদম ওভারলোডগুলির শব্দার্থকগুলি তাদের ওভারলোডগুলি ছাড়াই অভিন্ন।

এর অর্থ নির্বাহের নীতিটিতে অ্যালগরিদমের কোনও ব্যবহারকারীর দৃশ্যমান পার্থক্য নেই। আপনি আশা করতে পারেন যে অ্যালগরিদম ঠিক একই ফলাফল দেবে যেমন আপনি কোনও প্রয়োগের নীতি নির্দিষ্ট না করেন।


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সম্ভবত পুনরাবৃত্তির অবৈধকরণ ঘটবে।

ব্যর্থতার একটি উদাহরণ দেখুন যা আপনি লাইভ করবেন না ।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.