2014-01-07 74 views

回答

3

讓我們思考浮點原子能,從操作系統/硬件設計點......

原子公司的存在是因爲他們需要同步。大部分同步涉及什麼?句柄,標記,互斥,自旋鎖 - 只要每個用戶的一致性和用戶之間的不同,實際值無意義的事物。即使是像一個信號,其中值是更有意義 - 它仍然是關於計數而不是測量,所以32位是值得32位,無論我們認爲它代表。

其次,技術問題。幾乎任何我們可以編程的東西都是整數運算。不是那麼浮動 - 當C庫模擬FP操作時,這些原子將處於困難和不可能實現之間。即使在硬件上,FP操作通常會比整數慢,誰想要慢鎖? FPU本身的設計甚至可能使得難以實現原子操作 - 例如,如果它沒有任何直接訪問內存總線的協處理器接口。

二分之一,如果我們想要float,我們當然也想要double?但是double通常存在比機器字更大的問題,排除了許多架構上的負載和存儲的原子性。第三,當談到像atomics這樣的東西時,CPU架構師傾向於實現系統設計人員和操作系統人員所要求的東西,而操作系統人員通常不會真正喜歡浮點 - 愚蠢的額外寄存器來保存,減慢上下文開關...更多指令/硬件成本功率和複雜性的特點,如果客戶不希望他們...

因此,簡而言之,有沒有足夠的用例的,所以沒有硬件支持,所以沒有語言支持。當然,在某些體系結構中,您可以使用roll your own atomics,我想可能GPU計算可能對主要浮點硬件的同步有更多需求,那麼誰知道它是否會保持這種狀態呢?

1

啊,原來問題是標籤與圍棋個略有不同,所以這裏就是我大概要回答,對不起,如果它不是編輯的問題:)

一起去,你可以換全部的答案任何指針值與原子有點行程在不安全的黑暗的一面:

http://play.golang.org/p/aFbzUMhfEB

摘錄:

var uptr unsafe.Pointer 
var f1, f2 float64 

f1 = 12.34 
f2 = 56.78 
// Original values 
fmt.Println(f1, f2) 
uptr = unsafe.Pointer(&f1) 
atomic.SwapPointer(&uptr, unsafe.Pointer(&f2)) 
f1 = *(*float64)(unsafe.Pointer(uptr)) 
// f1 now holds the value of f2, f2 is untouched 
fmt.Println(f1, f2) 

的交換呼叫(等CAS其他原子操作)映射到CPU架構的指令,保證原子性(見https://stackoverflow.com/a/1762179/1094941有詳細介紹)。至於爲什麼沒有裝配支持浮筒,我不知道。

+0

OpenCL提供原子單精度浮點運算。它支持C的一個稍微小一點的子集。http://www.khronos.org/它的意思是可移植的,AFAIK。 –

1

爲了改進Go的上下文中的回答,我們可以使用https://golang.org/pkg/math/#Float64bitshttps://golang.org/pkg/math/#Float64frombits將float64與uint64s進行轉換,而無需直接使用不安全的軟件包。

鑑於uint64,我們可以使用所有可用的原子基元。

type AtomicFloat64 uint64 

func (f *AtomicFloat64) Value() float64 { 
    return math.Float64frombits(atomic.LoadUint64((*uint64)(f))) 
} 

func (f *AtomicFloat64) Add(n float64) float64 { 
    for { 
     a := atomic.LoadUint64((*uint64)(f)) 
     b := math.Float64bits(math.Float64frombits(a) + n) 
     if atomic.CompareAndSwapUint64((*uint64)(f), a, b) { 
      return 
     } 
    } 
} 
+1

這個答案不正確。您可以嘗試 ''' 變種X AtomicFloat64 x.Add(1) x.Add(1) x.Add(1) x.Value() - > -0.25肯定不是3 ''' 如果你想更好的方式看看這個代碼: https://github.com/prometheus/client_golang/blob/master/prometheus/value.go#L91 – zviadm

+0

你是絕對正確的!此代碼有一個錯誤。感謝您的注意,我會更新答案。 –

+0

不需要執行'a:= atomic.LoadUint64',因爲它可能會在下一個'if'語句之前更改。見https://golang.org/src/sync/atomic/64bit_arm.go?s=508:615#L27 – gobwas