Hi à tous !

Voilà, je vous explique mon problème:

Lorsque je parallélise une partie de calcul avec des doubles, j'ai un problème de précision (différence à 10^-15) sur des données de type double.

Voici un exemple de code qui illustre mon problème:

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
 
#include "stdafx.h"
#include <iostream>
#include <time.h>
#include <conio.h>
#include <Windows.h>
#include <ppl.h>
#include <iomanip>
int _tmain(int argc, _TCHAR* argv[])
{
 
	// Sequential computation
	double Sum	= 0.48022937707356972;	
	double Df	= 0.29988796445769539;
	clock_t startSequential = clock();
 
	for(int i = 0 ; i < 100 ; ++i)
	{
		Sum+=i*Df;
		Sleep(1);
	}
 
	clock_t endSequential = clock();
	clock_t finSequential = endSequential - startSequential;
 
	std::cout << "--------------SEQUENTIAL--------------" << std::endl;
	std::cout << "\tSum : " << std::setprecision(17) << Sum << std::endl;
	std::cout << "\tTime for computation : " << finSequential << std::endl;
 
	// Parallel computation
	clock_t startParallel = clock();
	Sum = 0.48022937707356972;
	Concurrency::critical_section mutexContention;
	Concurrency::parallel_for( 0, 100, [&]( int i )
	{
		mutexContention.lock();
		Sum+=i*Df;
		mutexContention.unlock();
		Sleep(1);
	});
 
	clock_t endParallel = clock();
	clock_t finParallel = endParallel - startParallel;
 
	std::cout << "--------------PARALLEL CONCURRENCY--------------" << std::endl;
	std::cout << "\tSum : " << std::setprecision(17) << Sum << std::endl;
	std::cout << "\tTime for computation : " << finParallel << std::endl;
 
	clock_t startParallelOpen_MP = clock();
	int imp;
	Sum=0.48022937707356972;
#pragma omp parallel for reduction(+:Sum)
	for( imp = 0 ; imp < 100 ; imp++)
	{
		Sum+=imp*Df;
		Sleep(1);
	}
 
	clock_t endParallelOpen_MP = clock();
	clock_t finParallelOpen_MP = endParallelOpen_MP - startParallelOpen_MP;
 
	std::cout << "--------------PARALLEL OPEN MP--------------" << std::endl;
	std::cout << "\tSum : " << std::setprecision(17) << Sum << std::endl;
	std::cout << "\tTime for computation : " << finParallelOpen_MP << std::endl;
 
	std::cout<<std::endl<<"press any key to exit..." <<std::endl;
	_getch();
	return 0;
}
Alors cet exemple présente dans un premier temps un calcul séquentiel dans lequel je fais des additions successives sur des chiffres demandant de fortes précisions sur les arrondis. Le résultat pour ce dernier est tout le temps : 1484.9256534426663

Le problème se situe dans les deux autres cas lorsque je "parallélise" la boucle fort avec openMP ou avec l'API PPL de microsoft (uniquement disponible sous VS2010), j'obtiens des résultats qui ne sont pas vraiment déterministes, avec une erreur d'arrondi. C'est à dire que parfois j'ai 1484.9256534426654, ou 1484.9256534426661, ... L'erreur est certes "infime", mais j'ai besoin d'une telle précision De plus, à moins que je me trompe, mais les données partagées ont l'aire bien protégées

Est ce que quelqu'un a déjà eu un problème similaire ?

Notez que je suis sur XP SP3, que je compile avec l'option "floating point" à "precise", que je tourne sur un Core2Duo et que j'ai le même comportement avec un build sous VS2005 et 2008 (sans PPL bien sûr !).

Merci d'avance et bonne journée