Le cas 0, « application concurrente d'un calcul sur une séquence de nombres », tel que proposé dans vos notes de cours, se présente comme suit.
struct Probleme
{
virtual bool est_resolu() const volatile = 0;
virtual void resoudre_un() volatile = 0;
virtual ~Probleme() throw()
{ }
};
unsigned long __stdcall calcul(void *p)
{
for (Probleme *prob = static_cast<Probleme *>(p);
!prob->est_resolu(); )
prob->resoudre_un();
return 0UL;
}
#include "Mutex.h"
#include <vector>
using std::vector;
#include <cmath>
using std::sqrt;
class RacinesCarrees
: public Probleme
{
typedef vector<double> vdbl;
vdbl valeurs_;
vdbl racines_;
Mutex mutex_;
void resoudre_un()
{
if (racines_.size() != valeurs_.size())
racines_.push_back
(sqrt(valeurs_[racines_.size()]));
}
bool est_resolu() const
{ return racines_.size() == valeurs_.size(); }
public:
template <class Itt>
RacinesCarrees(Itt debut, Itt fin)
: valeurs_(debut, fin)
{
}
bool est_resolu() const volatile
{
Autoverrou av(mutex_);
return const_cast<const RacinesCarrees*>(this)->est_resolu();
}
void resoudre_un() volatile
{
Autoverrou av(mutex_);
const_cast<RacinesCarrees*>(this)->resoudre_un();
}
vector<double> resultats() const
{ return racines_; }
};
#include <cstdlib>
using std::srand;
using std::rand;
double GenererValeur() throw ()
{ return static_cast<double>(rand()%1000+1); }
#include <iostream>
#include <ctime>
#include <algorithm>
#include <windows.h>
int main()
{
using std::begin;
using std::end;
using std::cout;
using std::endl;
using std::clock;
using std::clock_t;
using std::time;
using std::for_each;
using std::generate;
const int N = 1000000;
vector<double>valeurs(N);
srand(static_cast<unsigned int>(time(0)));
generate(valeurs.begin(), valeurs.end(), [](){
return static_cast<double>(rand()%1000+1);
});
const int MAX_THREADS = 10;
for (int n = 1; n <= MAX_THREADS; ++n)
{
RacinesCarrees rc(Valeurs, Valeurs+NB_VALEURS);
vector<HANDLE>v(n);
for (int i = 0; i < n; ++i)
v[i] = CreateThread(0, 0, calcul, &rc, CREATE_SUSPENDED, 0);
clock_t avant = clock();
for_each(v.begin(), v.end(), ResumeThread);
WaitForMultipleObjects(n, &v[0], TRUE, INFINITE);
clock_t apres = clock();
for_each(v.begin(), v.end(), CloseHandle);
cout << "Temps total, " << N << " valeurs, " << n << " thread(s): "
<< static_cast<double>(apres-avant)/
CLOCKS_PER_SEC * 1000
<< " ms." << endl;
}
}
Sur mon petit ordinateur portatif, compilé avec Visual Studio 2010, configuration Release, et en prenant bien entendu soin d'ajouter _SECURE_SCL=0 aux options du préprocesseur pour désactiver les (franchement inutiles et nuisibles) Checked Iterators, j'obtiens :
Temps total, 1000000 valeurs, 1 thread(s): 2425 ms.
Temps total, 1000000 valeurs, 2 thread(s): 10082 ms.
Temps total, 1000000 valeurs, 3 thread(s): 11696 ms.
Temps total, 1000000 valeurs, 4 thread(s): 11454 ms.
Temps total, 1000000 valeurs, 5 thread(s): 8826 ms.
Temps total, 1000000 valeurs, 6 thread(s): 9085 ms.
Temps total, 1000000 valeurs, 7 thread(s): 8742 ms.
Temps total, 1000000 valeurs, 8 thread(s): 8513 ms.
Temps total, 1000000 valeurs, 9 thread(s): 10353 ms.
Temps total, 1000000 valeurs, 10 thread(s): 9267 ms.
Appuyez sur une touche pour continuer...