Programim dhe zhvillim, javascript, python, php, html

A është i garantuar një lexim prej 8 bajte në intel x86 modern nëse 8 bajt shkruhet nga fije të ndryshme?

struct Data {
    double a;
    double b;
    double c;
};

A do të ishte e arsyeshme leximi i secilës dyshe, nëse lexohet në një fill tjetër, por vetëm një fije tjetër po i shkruan secilit prej a,b,c?

Cili është skenari nëse siguroj se Data është përafruar?

struct Data {double a,b,c; } __attribute__((aligned(64));

Kjo do të siguronte që secila prej a,b,c të jetë e rreshtuar në 64,64+8, 64+16... kështu që gjithmonë të rreshtuar në kufirin 8*8=64 bit.

Kjo pyetje kërkesat e shtrirjes për udhëzimet atomic x86 dhe përgjigja e saj më bën të mendoj se është plotësisht i vlefshëm për t'i shkruar Data::a/b/c nga një temë tjetër dhe njëkohësisht për t'i lexuar ato pa përdorur std::atomic.

Po, e di që std::atomic do ta zgjidhte këtë, por çështja nuk është kjo.


  • Do të ishte e sigurt nëse do të kishte një garanci që përpiluesi do të përdorte ato udhëzime atomike x86. Plotësimi i kërkesave të shtrirjes nuk do të thotë se përpiluesi do t'i përdorë ato udhëzime. Sigurimi i një garancie të tillë do të nënkuptonte humbjen e mundësive të optimizimit, kështu që unë do të sugjeroja që nuk ka gjasa të jetë e paracaktuar. Pra, nëse nuk shkruani kodin tuaj për të siguruar sigurinë e fillit (p.sh. duke përdorur std::atomic), nuk ka asnjë garanci që një lexim do të ishte i arsyeshëm nëse një shkrim i së njëjtës ndryshore ndodh në një fill tjetër. 27.11.2019
  • Pra, çfarë në të vërtetë është pyetja, ajo përzien semantikën e nivelit të makinës dhe C++ në një mënyrë të çuditshme, dhe përgjigja për secilën është e kundërta, sepse C++ pëlqen të heqë garancitë që ju ka dhënë hardueri. 27.11.2019
  • @harold Unë jam nën një pajisje specifike, Intel i7, në këtë rast... dhe po pyesja veten nëse mund të përdorja thjesht një strukturë dyshe të rreshtuara dhe të lexoja dhe shkruaja nga/tek to pa atomik, pasi kërkesa ime është vetëm një lexim i arsyeshëm për 8 bajt të rreshtuar. 27.11.2019
  • @themagicalyang në montim ju mund ta bëni këtë. Në C++, ndoshta, por përpiluesi mund të shkatërrojë gjërat. Duke lënë mënjanë gjërat tepër hipotetike, mund të lëvizë një dyqan nga një lak dhe ta bëjë atë vetëm një herë në fund, ose të lëvizë një ngarkesë nga një lak dhe ta bëjë atë vetëm një herë në fillim - atëherë nuk ka ngarkesa të grisura ose diçka të tillë por temat tuaja nuk do të komunikonin. 27.11.2019

Përgjigjet:


1

Po, ngarkesat/magazinat e rreshtuara 8 bajt garantohen atomike nga x86 ISA, që nga P5 Pentium. Pse caktimi i numrave të plotë është në një linjë të natyrshme atomike të ndryshueshme në x86?

Por kjo është C++; nuk ka asnjë garanci që dyqanet dhe ringarkimet nuk janë të optimizuara larg. Shkrimi në një fill dhe leximi në një tjetër është sjellje e padefinuar në C++; përpiluesit lejohen të supozojnë se nuk ndodh, thyerja e supozimeve naive. Kjo i lejon ata të mbajnë objekte C++ në regjistra përgjatë leximeve/shkrimeve të shumta, vetëm përfundimisht duke ruajtur vlerën përfundimtare. (duke përfshirë variablat globale ose memorien e drejtuar nga ndonjë tregues.)

Meqenëse nuk e dinit që volatile ose atomic<double> nevojiten për këtë arsye, më mirë lexoni për të tjera gjërat që bën atomic<> për ju, si p.sh. porositja e wrt. operacione të tjera nëse nuk përdorni memory_order_relaxed (parazgjedhja është seq_cst që i bën dyqanet të shtrenjta, por në ngarkesat x86 janë ende po aq të lira). Dhe (si volatile) supozimi se thread-et e tjera mund të kenë modifikuar një objekt midis akseseve në këtë thread. Shikoni A mund të jetë num++ atomike për 'int num'?, disa nga e cila është e rëndësishme për ngarkesat dhe depozitat e FP.

Programimi pa kyçje në C++ nuk është i thjeshtë, nëse nuk keni zero nevojë për sinkronizim / renditje. Atëherë ju "thjesht" duhet të siguroheni që t'i tregoni përpiluesit se çfarë do të thoni, me atomic<T>, ose si hak me double.


Meqenëse std::atomic<double> me mo_relaxed e GCC nuk përpilohet në mënyrë efikase, ju mund të krijoni të tuajën duke i bërë anëtarët volatile nëse ju intereson vetëm transportueshmëria. (ose edhe transmetimi në (volatile double*) si makrot READ_ONCE / WRITE_ONCE të kernelit Linux). Me clang, thjesht mund të përdorni atomic<double> me memory_order_relaxed dhe gjërat do të përpilohen në mënyrë efikase. Shiko C++20 std::atomic‹float›- std::atomic‹u .specializimet për shembull se çfarë mund të bëni përpara C++20; C++20 shton vetëm shtesë/nën atomike RMW për double, kështu që ju nuk keni nevojë të rrotulloni tuajën me një lak CAS.

volatile ndoshta do të vazhdojë të mposhtë vektorizimin automatik, por sigurisht që mund të përdorni _mm_load_pd ose çfarëdo. (Shih gjithashtu Atomic double floating pika ose ngarkesa/ruajtja e vektorit SSE/AVX në x86_64 - vini re se ngarkesa/magazina SIMD nuk është domosdoshmërisht atomike edhe nëse është e linjës. Gjithashtu e padokumentuar është nëse ato janë atomike për element, megjithëse është< /em> Unë mendoj se është e sigurt të supozohet. Për-element atomiciteti i ngarkesës vektoriale/ruani dhe grumbulloni/shpërndani?)

Kur të përdoret volatile me shumë threading? normalisht kurrë nuk mund të përdoret. , përveç ndoshta si një zgjidhje për GCC që nuk do të emetojë asm efikas për atomic<double>, dhe ku ne e dimë saktësisht se si volatile përpilohet në asm.


BTW, ju nevojitet vetëm alignas(8) për t'u siguruar që anëtarët të jenë të rreshtuar 8 bajt. Përafrimi i strukturës në një linjë të tërë të memories së memories nuk dëmton, përveç nëse humbet hapësirë.

Për performancën: nëse threads të ndryshëm përdorin variabla të ndryshëm në të njëjtën linjë cache, kjo është "false share" dhe e tmerrshme për performancën. Mos i gruponi variablat tuaja të përbashkëta së bashku në një strukturë, përveç nëse ato zakonisht lexohen ose shkruhen si grup. Përndryshe, ju patjetër i dëshironi ato në linja të veçanta memorie 64-bajtëshe.


Vini re se një garë e të dhënave në një volatile është ende një sjellje e papërcaktuar ISO C++, por nëse jeni duke përdorur GNU C (siç kërkohet nga __attribute__-ja juaj), është shumë mirë e përcaktuar. Kerneli Linux e përdor atë për atomin e tij të mbështjellë me dorë (së bashku me asm në linjë për barrierat), kështu që mund të supozoni se nuk do të jetë e pambështetur qëllimisht së shpejti.

TL:DR: në GNU C bën pak a shumë punë të mendosh për volatile si atomike me mo_relaxed, për objektet e rreshtuara mjaft të vogla që të jenë atomike natyrale.

27.11.2019
  • Unë do të shtoja se nëse tema të ndryshme kanë qasje në anëtarë të ndryshëm, ndarja e rreme është diçka për t'u marrë parasysh. 27.11.2019
  • @AProgrammer Ndarja false është vetëm kur shkruajnë tema të ndryshme apo jo? Nëse vetëm një temë shkruan dhe të tjerët lexojnë, atëherë nuk ka asnjë problem. 27.11.2019
  • @themagicalyang: Jo mjaft. Nëse filli A po kalon, rilexoni double a çdo përsëritje në rast se ndryshon, kjo mund të godasë në cache. Ruajtja e fillit B në double b në të njëjtën linjë si a do ta zhvlerësojë atë rresht në të gjitha bërthamat e tjera, duke ndërhyrë me fillin A edhe nëse filli A nuk lexon kurrë b. 27.11.2019
  • Materiale të reja

    Masterclass Coroutines: Kapitulli-3: Anulimi i korutinave dhe trajtimi i përjashtimeve.
    Mirë se vini në udhëzuesin gjithëpërfshirës mbi Kotlin Coroutines! Në këtë seri artikujsh, unë do t'ju çoj në një udhëtim magjepsës, duke filluar nga bazat dhe gradualisht duke u thelluar në..

    Faketojeni derisa ta arrini me të dhënat false
    A e gjeni ndonjëherë veten duke ndërtuar një aplikacion të ri dhe keni nevojë për të dhëna testimi që duken dhe duken më realiste ose një grup i madh të dhënash për performancën e ngarkesës...

    Si të përdorni kërkesën API në Python
    Kërkesë API në GitHub për të marrë depot e përdoruesve duke përdorur Python. Në këtë artikull, unë shpjegoj procesin hap pas hapi për të trajtuar një kërkesë API për të marrë të dhëna nga..

    Një udhëzues hap pas hapi për të zotëruar React
    Në këtë artikull, do të mësoni se si të krijoni aplikacionin React, do të mësoni se si funksionon React dhe konceptet thelbësore që duhet të dini për të ndërtuar aplikacione React. Learning..

    AI dhe Psikologjia — Pjesa 2
    Në pjesën 2 të serisë sonë të AI dhe Psikologji ne diskutojmë se si makineritë mbledhin dhe përpunojnë të dhëna për të mësuar emocione dhe ndjenja të ndryshme në mendjen e njeriut, duke ndihmuar..

    Esencialet e punës ditore të kodit tim VS
    Shtesat e mia të preferuara - Git Graph 💹 Kjo shtesë është vërtet e mahnitshme, e përdor përpara se të filloj të punoj për të kontrolluar dy herë ndryshimet dhe degët më të fundit, mund të..

    Pse Python? Zbulimi i fuqisë së gjithanshme të një gjiganti programues
    Në peizazhin gjithnjë në zhvillim të gjuhëve të programimit, Python është shfaqur si një forcë dominuese. Rritja e tij meteorike nuk është rastësi. Joshja e Python qëndron në thjeshtësinë,..


    © 2024 albai.ru, Programim dhe zhvillim, javascript, python, php, html