2012-03-27 17 views
8

मैंने बढ़ावा देने का हिस्सा संकलित किया है - ibeta_inv फ़ंक्शन - .Net 64 बिट असेंबली में और यह तब तक अच्छा काम करता है जब तक कि मैंने इसे एकाधिक थ्रेड से कॉल करना शुरू नहीं किया। फिर यह मौलिक रूप से गलत परिणाम देता है।बूस्ट गणित (ibeta_inv फ़ंक्शन) थ्रेड सुरक्षित नहीं है?

// Boost.h 

#pragma once 

#include <boost/math/special_functions/beta.hpp> 

using namespace boost::math; 

namespace Boost { 

    public ref class BoostMath 
    { 
    public: 
     double static InverseIncompleteBeta(double a, double b, double x) 
     { 
      return ibeta_inv(a,b,x); 
     } 
    }; 
} 

किसी को भी करने से पहले इस की कोशिश की है:

मैं इस कोड (C++/CLI) का उपयोग कर यह पालन किया?

मैंने इसे बाहर नहीं किया है। नेट, इसलिए मुझे नहीं पता कि यह कारण क्या है, लेकिन मुझे वास्तव में यह नहीं पता कि क्यों, यह महान एकल थ्रेडेड काम करता है।

प्रयोग (सी #):

private void calcBoost(List<Val> vals) 
{ 
    //gives WRONG results (sometimes): 
    vals.AsParallel().ForAll(v => v.BoostResult = BoostMath.InverseIncompleteBeta(v.A, v.B, v.X)); 
    //gives CORRECT results: 
    vals.ForEach(v => v.BoostResult = BoostMath.InverseIncompleteBeta(v.A, v.B, v.X)); 
} 

अद्यतन: जैसा कि नीचे मेरी टिप्पणी में देखा जा सकता है - मैं सब पर अब और है कि यह एक बूस्ट समस्या है यकीन नहीं है। शायद यह कुछ अजीब PLinq सी ++/सीएलआई बग ??? मैं blaffed हूँ और बाद में और तथ्यों के साथ वापस आ जाएगा।

+2

दस्तावेज़ीकरण का कहना है कि पूरे boost.math को थ्रेड सुरक्षित होना चाहिए जब तक कि आप अंतर्निहित फ्लोटिंग पॉइंट प्रकारों का उपयोग करें (जो, जैसा कि मैंने देखा है, आप करते हैं)। शायद आपको एक बग फाइल करना चाहिए? http://www.boost.org/doc/libs/release/libs/math/doc/sf_and_dist/html/math_toolkit/main_overview/threads.html – stanwise

+0

यदि कुछ और नहीं हो जाता है, तो मैं इसे मूल C++ में आज़मा सकता हूं ऐप और देखें कि समस्या बनी हुई है या नहीं। यदि ऐसा है, तो एक बग रिपोर्ट केवल एकमात्र चीज हो सकती है, क्योंकि मैं स्रोत कोड में कुछ भी नहीं खोज सकता। दयालुता हालांकि ... यह उलटा अपूर्ण बीटा फ़ंक्शन के हमारे वर्तमान कार्यान्वयन के रूप में तेज़ी से दोगुना चलता है। –

+0

दिलचस्प!दो विचार दिमाग में आते हैं: (1) ट्रिपल-चेक आपने मल्टीथ्रेड मोड में बढ़ावा दिया है (वर्तमान संस्करण अभी भी भेद बनाते हैं), और (2) इस उद्धरण, दस्तावेज से @stanwise जुड़े हुए हैं: 'बाद की सीमा का कारण संरचनाओं का उपयोग करके प्रतीकात्मक स्थिरांक शुरू करने की आवश्यकता है ... इस मामले में टी के रचनाकारों को चलाने की आवश्यकता है, जिससे संभावित दौड़ की स्थिति बढ़ती है। 'मैं खुले तौर पर आश्चर्य करता हूं कि आपका कोड अप्रत्याशित रूप से इस दौड़ की स्थिति को उजागर करता है, और मैं पूरी तरह से वापस आ गया हूं एक बग के रूप में रिपोर्ट करने पर stanwise। – MrGomez

उत्तर

2

मुझे सी ++/सीएलआई 64 बिट प्रोजेक्ट में बढ़ावा देने के हिस्से को समाहित किया गया है और इसे ठीक से सी # से उपयोग करें।

तो मैं अपने ही बूस्ट आवरण में अपनी सी ++ वर्ग में फेंक दिया और सी # परियोजना के लिए इस कोड कहा:

private class Val 
    { 
     public double A; 
     public double B; 
     public double X; 
     public double ParallellResult; 
    } 

    private static void findParallelError() 
    { 
     var r = new Random(); 

     while (true) 
     { 
      var vals = new List<Val>(); 
      for (var i = 0; i < 1000*1000; i++) 
      { 
       var val = new Val(); 
       val.A = r.NextDouble()*100; 
       val.B = val.A + r.NextDouble()*1000; 
       val.X = r.NextDouble(); 
       vals.Add(val); 
      } 

      // parallel calculation 
      vals.AsParallel().ForAll(v => v.ParallellResult = Boost.BoostMath.InverseIncompleteBeta(v.A, v.B, v.X)); 

      /sequential verification 
      var error = vals.Exists(v => v.ParallellResult != Boost.BoostMath.InverseIncompleteBeta(v.A, v.B, v.X)); 
      if (error) 
       return; 
     } 
    } 

और यह सिर्फ निष्पादित करता है "हमेशा के लिए"। समानांतर परिणाम अनुक्रमिक परिणामों के बराबर होते हैं। यहां कोई धागा असुरक्षित नहीं है ...

क्या मैं सुझाव देता हूं कि आप बूस्ट की ताजा प्रति डाउनलोड करें और इसे पूरी तरह से नई परियोजना में शामिल करें और इसे आजमाएं?

मुझे यह भी पता है कि आपने अपना परिणाम "बूस्ट रिसेट" कहा है ... और "हमारे वर्तमान कार्यान्वयन" के बारे में कुछ टिप्पणियों में उल्लेख किया है। वास्तव में आप अपने परिणाम की तुलना फिर से कर रहे हैं? "सही" की आपकी परिभाषा क्या है?

+0

बोनकर्स। मुझे इस प्रश्न के लिए माफी मांगनी होगी। यह पूरी तरह से गलत धारणाओं पर आधारित है। मर्फी लॉ की ताकत के लिए श्रद्धांजलि एक कह सकता है। त्रुटि उत्पादन वोकोड में है जिसे मैं तेज़ करने की कोशिश कर रहा था। –

4

यह महत्वपूर्ण है कि Val कक्षा थ्रेडसेफ है।

यह सुनिश्चित करने का एक आसान तरीका यह अपरिवर्तनीय बनाना होगा, लेकिन मुझे लगता है कि आपके पास BoostResult भी लिखा जाना चाहिए। तो उसे volatile होना चाहिए, या लॉकिंग का कुछ रूप होना चाहिए।

public sealed class Val 
{ 
    // Immutable fields are inheriently threadsafe 
    public readonly double A; 
    public readonly double B; 
    public readonly double X; 

    // volatile is an easy way to make a single field thread safe 
    // box and unbox to allow double as volatile 
    private volatile object boostResult = 0.0; 

    public Val(double A, double B, double X) 
    { 
     this.A = A; 
     this.B = B; 
     this.X = X; 
    } 

    public double BoostResult 
    { 
     get 
     { 
      return (double)boostResult; 
     } 
     set 
     { 
      boostResult = value; 
     } 
    } 
} 

ताला संस्करण: (this question देख निर्धारित करने के लिए जो आपके आवेदन के लिए सबसे उचित होगा)

public sealed class Val 
{ 
    public readonly double A; 
    public readonly double B; 
    public readonly double X; 

    private readonly object lockObject = new object(); 
    private double boostResult; 

    public Val(double A, double B, double X) 
    { 
     this.A = A; 
     this.B = B; 
     this.X = X; 
    } 

    public double BoostResult 
    { 
     get 
     { 
      lock (lockObject) 
      { 
       return boostResult; 
      } 
     } 
     set 
     { 
      lock (lockObject) 
      { 
       boostResult = value; 
      } 
     } 
    } 
} 

और अगर आपको लगता 6 लाख ताले धीमी गति से हो जाएगा, सिर्फ इस प्रयास करें:

using System; 

namespace ConsoleApplication17 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      { //without locks 
       var startTime = DateTime.Now; 
       int i2=0; 
       for (int i = 0; i < 6000000; i++) 
       { 
        i2++; 
       } 
       Console.WriteLine(i2); 
       Console.WriteLine(DateTime.Now.Subtract(startTime)); //0.01 seconds on my machine 
      } 
      { //with locks 
       var startTime = DateTime.Now; 
       var obj = new Object(); 
       int i2=0; 
       for (int i = 0; i < 6000000; i++) 
       { 
        lock (obj) 
        { 
         i2++; 
        } 
       } 
       Console.WriteLine(i2); 
       Console.WriteLine(DateTime.Now.Subtract(startTime)); //0.14 seconds on my machine, and this isn't even in parallel. 
      } 
      Console.ReadLine(); 
     } 
    } 
} 
+0

नहीं, यह सही नहीं है। संस्करण एक के साथ - मुझे अभी भी वही समस्या मिलती है (और एक डबल अस्थिर नहीं हो सकता है, लेकिन यह अप्रासंगिक है क्योंकि जब तक कि सभी गणना नहीं की जाती तब तक मैं इसे तब तक नहीं पढ़ता)। संस्करण दो सवाल से बाहर है क्योंकि मैं इसे बना रहा हूं छह मिलियन बार कॉल करें और यदि मैं हर बार लॉक करने जा रहा हूं - हमारा वर्तमान कार्यान्वयन बहुत तेज़ होगा। लेकिन: माँ राजा वैल एक संरचना काम करता है !!! –

+0

@ डैनबीस्ट्रॉम ओह हाँ, क्षमा करें। अस्थिर संस्करण अद्यतन किया है। जब तक आप अपने स्ट्रक्चर संस्करण से खुश न हों, तब तक मुझे दिलचस्पी होगी यदि नया अस्थिर संस्करण काम करता है। आप इसे पढ़ नहीं सकते हैं, लेकिन यदि यह मुख्य धागे द्वारा लिखा गया है, यहां तक ​​कि केवल 'नए वैल' के इंटिलाइजेशन के दौरान, इसे उस धागे से कैश किया जा सकता है जिसे मैं मानता हूं। – weston

+1

मुझे नहीं लगता कि आपको यह अस्थिर अवधारणा सही मिल गई है। यह संकलक को बताता है कि संकलक कोड का उत्पादन नहीं कर सकता है जो एक रजिस्टर में चर को कैश करता है - क्योंकि यह किसी भी समय बदल सकता है। इसमें कोई और गहरा "थ्रेड सुरक्षित" मीटिंग नहीं है। कम से कम मेरे ज्ञान के लिए नहीं ... मुझे सही करने के लिए स्वतंत्र महसूस करें! और, नहीं, मैं अपने संरचना समाधान से खुश नहीं हूं ... जब तक मुझे पता न हो कि बोनकर्स क्या चल रहा है !!! लेकिन इसने मुझे विश्वास करने के लिए प्रोत्साहित किया है कि मैं यह काम कर सकता हूं ... किसी भी तरह! यकीन नहीं है कि अगर मैं आपकी टिप्पणी के लिए नहीं था तो मैंने संरचना की कोशिश की होगी! –

संबंधित मुद्दे