Commit cf80e8b5 authored by Grégory Mounié's avatar Grégory Mounié

ajout version avec timer et code C11 optimisé

version C11 va plus vite, mais cout de lecture/dev/maintenance important
parent dbe0a5d1
CXXFLAGS= -std=gnu++11 -Wall -Werror -O3
CC= g++
LDLIBS+= -lpthread
CFLAGS+= -Wall -g -O2 -std=gnu11
all: dekker peterson
all: dekker peterson dekkerAvecC11
dekker: dekker.o
dekkerAvecC11: inc.o dekkerC11.o dekkerAvecC11.o
dekkerC11.o: CC=gcc
peterson: peterson.o
clean:
rm -f dekker dekker.o peterson peterson.o
rm -f dekker dekker.o peterson peterson.o dekkerC11.o dekkerAvecC11.o
/* Implantation de Dekker en C++ */
/* Verification du fonctionnement
sur l'incrementation d'une variable
entière non atomique (mais volatile) */
#include <atomic>
#include <iostream>
#include <thread>
#include <chrono>
#include "dekkerC11.h"
#include "inc.h"
using namespace std;
// le compteur changeant magiquement,
// il faut indiquer au compilateur
// son necessaire rechargement
extern volatile int compteur;
// /* Juste avec volatile */
// /* marche pas ! mis dans inc.cpp pour éviter les optimisations */
// void incrementeur(int me, int other, int *compteur, int stride) {
// for(int i=0; i < NBINC; i++) {
// (*(compteur+i*stride))++;
// }
// }
/* Dekker */
/* sans operations atomiques de synchro */
/* juste volatile pour les variables */
/* marche pas non plus ! */
volatile bool fdemande[2] = {};
volatile int ftour;
void fdebut_sc(int me, int other) {
debut:
fdemande[me] = true;
if (fdemande[other]) {
if (ftour == me) {
while(fdemande[other]);
}
else {
fdemande[me] = false;
while(ftour != me);
goto debut;
}
}
}
void ffin_sc(int me, int other) {
ftour = other;
fdemande[me] = false;
}
void incrementeur_fdekker(int me, int other) {
for(int i=0; i < NBINC; i++) {
fdebut_sc(me, other);
compteur++;
ffin_sc(me, other);
}
}
/* Dekker */
/* avec ecritures synchro. par C++ */
/* semantique seq. (le defaut) */
atomic_bool demande[2] = {};
atomic_int tour;
void debut_sc(int me, int other) {
debut:
demande[me] = true;
if (demande[other]) {
if (tour == me) {
while(demande[other]);
}
else {
demande[me] = false;
while(tour != me);
goto debut;
}
}
}
void fin_sc(int me, int other) {
tour = other;
demande[me] = false;
}
void incrementeur_dekker(int me, int other) {
for(int i=0; i < NBINC; i++) {
debut_sc(me, other);
compteur++;
fin_sc(me, other);
}
}
int main(int argc, char **argv) {
cout << u8"** Increm. sans dekker **" << endl;
auto d = chrono::high_resolution_clock::now();
thread t1 = thread(incrementeur, 0, 1, (int*) &compteur, 0);
thread t2 = thread(incrementeur, 1, 0, (int*) &compteur, 0);
t1.join();
t2.join();
auto e = chrono::high_resolution_clock::now();
cout << compteur << "/" << NBINC * 2 << " en "
<< chrono::duration_cast<chrono::nanoseconds>(e-d).count() << " ns" << endl;
compteur = 0;
cout << u8"** Increm. dekker + volatile **" << endl;
d = chrono::high_resolution_clock::now();
thread t3 = thread(incrementeur_fdekker, 0, 1);
thread t4 = thread(incrementeur_fdekker, 1, 0);
t3.join();
t4.join();
e = chrono::high_resolution_clock::now();
cout << compteur << "/" << NBINC * 2 << " en "
<< chrono::duration_cast<chrono::nanoseconds>(e-d).count() << " ns" << endl;
cout << u8"** Increm dekker + atomic var **" << endl;
d = chrono::high_resolution_clock::now();
compteur = 0;
thread t5 = thread(incrementeur_dekker, 0, 1);
thread t6 = thread(incrementeur_dekker, 1, 0);
t5.join();
t6.join();
e = chrono::high_resolution_clock::now();
cout << compteur << "/" << NBINC * 2 << " en "
<< chrono::duration_cast<chrono::nanoseconds>(e-d).count() << " ns" << endl;
cout << u8"** Increm dekker + atomic var + modele memoire **" << endl;
d = chrono::high_resolution_clock::now();
compteur = 0;
thread t7 = thread(incrementeur_dekker_mm, 0, 1);
thread t8 = thread(incrementeur_dekker_mm, 1, 0);
t7.join();
t8.join();
e = chrono::high_resolution_clock::now();
cout << compteur << "/" << NBINC * 2 << " en "
<< chrono::duration_cast<chrono::nanoseconds>(e-d).count() << " ns" << endl;
}
/* Implantation de Dekker en C-11 */
/* Verification du fonctionnement
sur l'incrementation d'une variable
entière non atomique (mais volatile) */
#include <stdatomic.h>
#include <stdbool.h>
// attention à mettre la même valeur en C et C++
#define NBINC 400000
extern volatile int compteur;
/* Dekker */
/* avec ecritures synchro. par C-11 */
/* semantique release/acquire */
atomic_bool demande_mm[2] = {};
atomic_int tour_mm;
void debut_sc_mm(int me, int other) {
debut:
atomic_store_explicit(& demande_mm[me], true, memory_order_seq_cst);
if (atomic_load_explicit(& demande_mm[other], memory_order_acquire)) {
if (atomic_load_explicit(& tour_mm, memory_order_acquire) == me) {
while(atomic_load_explicit(& demande_mm[other],
memory_order_acquire));
}
else {
atomic_store_explicit(& demande_mm[me], false,
memory_order_release);
while(atomic_load_explicit(& tour_mm, memory_order_acquire)
!= me);
goto debut;
}
}
}
void fin_sc_mm(int me, int other) {
atomic_store_explicit(& tour_mm, other, memory_order_relaxed);
atomic_store_explicit(& demande_mm[me], false, memory_order_release);
}
void incrementeur_dekker_mm(int me, int other) {
for(int i=0; i < NBINC; i++) {
debut_sc_mm(me, other);
compteur++;
fin_sc_mm(me, other);
}
}
/* Implantation de Dekker en C-11 */
/* Verification du fonctionnement
sur l'incrementation d'une variable
entière non atomique (mais volatile) */
extern "C" {
extern volatile int compteur;
void debut_sc_mm(int me, int other);
void fin_sc_mm(int me, int other);
void incrementeur_dekker_mm(int me, int other);
}
#include "inc.h"
volatile int compteur = 0;
/* Juste avec volatile */
/* marche pas ! */
void incrementeur(int me, int other, int *compteur, int stride) {
for(int i=0; i < NBINC; i++) {
(*(compteur+i*stride))++;
}
}
#ifndef INC_H
#define INC_H
void incrementeur(int me, int other, int *compteur, int stride);
constexpr int NBINC= 400000;
#endif
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment