दिलचस्प पोस्ट
structs के साथ c ++ सॉर्ट करें क्यों मूल्य पर अनिर्धारित है। तब () वादा करने के लिए जंजीर? कैसे सिम्युलेटर में परीक्षण आईएडी बैनर प्रदर्शित करने के लिए जावा स्विंग में MouseMotionListener, घटकों के अंदर घटकों के साथ इसे उपयोग करते हुए रन-टाइम त्रुटि 1004 एक्सेल 2013 क्या विकल्प सख्त और विकल्प स्पष्ट करते हैं? समाधान में प्रोजेक्ट निर्भरता का उपयोग करते हुए MSBuild संदर्भों (DLL फ़ाइलों) को कॉपी नहीं करता है एंड्रॉइड वेबव्यू में फ़ॉन्ट साइज को कैसे बदल सकता है? सभी ब्राउज़रों में वेब पेज कैशिंग को कैसे नियंत्रित किया जाए? आइटम्स कंट्रोल में आइटम्स के बीच एक विभाजक कैसे जोड़ा जा सकता है आईओसी / डीआई – मुझे प्रविष्टि आवेदन में सभी परतों / विधानसभाओं का संदर्भ क्यों मिला है? यदि वे regexp का उपयोग नहीं कर रहे हैं, तो HTML पार्स कैसे काम करता है? एक विशिष्ट मान (ओरेकल) के लिए सभी टेबल्स में सभी फ़ील्ड खोजें आरवीएम स्थापना काम नहीं कर रहा है: "आरवीएम एक फ़ंक्शन नहीं है" एक गतिविधि संदर्भ के बाहर से शुरू कर रहा है

फ्लोट को एक बाइट में बदलने का सबसे तेज़ तरीका क्या है?

मैं एक byte[] को जितना जल्दी संभव हो, एक float[] से प्राप्त करना चाहूंगा (पूरी तरह से एक कलाकार के माध्यम से, संभवतः)। असुरक्षित कोड ठीक है धन्यवाद!

मैं एक बाइट सरणी को फ्लोट एरे से 4 बार अधिक समय देख रहा हूं (बाइट सरणी का आयाम फ्लोट सरणी के 4 गुना होगा, क्योंकि प्रत्येक फ़्लैट 4 बाइट्स से बना है)। मैं इसे BinaryWriter को पास कर दूँगा

संपादित करें : "समीप अनुकूलन" को चिल्लाने वाले उन आलोचकों के लिए: मैंने अनुकूलित किए जाने से पहले एंटीएस प्रोफाइलर का उपयोग करके यह बेंचमार्क किया है I एक महत्वपूर्ण गति में वृद्धि हुई थी क्योंकि फ़ाइल में एक लिखने वाली कैश है और डिस्क पर सेक्टर आकार से मिलान करने के लिए फ्लोट एआरए बिल्कुल आकार का होता है। द्विआधारी लेखक pinvoke डी डन32 एपीआई के साथ बनाई गई एक फ़ाइल संभाल को लपेटता है अनुकूलन तब होता है जब से यह फ़ंक्शन कॉल की संख्या को कम करता है।

और, स्मृति के संबंध में, यह एप्लिकेशन बड़े पैमाने पर कैश बनाता है जो बहुत मेमोरी का उपयोग करते हैं। मैं एक बार बाइट बफर को आवंटित कर सकता हूं और इसे कई बार पुन: उपयोग कर सकता हूं- इस विशेष आवृत्ति में डबल मेमोरी उपयोग ऐप के संपूर्ण स्मृति खपत में एक गोलऑफ त्रुटि के बराबर है।

इसलिए मुझे लगता है कि यहाँ अध्याय समय से पहले मान्यताओं को नहीं बनाना है;)

वेब के समाधान से एकत्रित समाधान "फ्लोट को एक बाइट में बदलने का सबसे तेज़ तरीका क्या है?"

यदि आप कोई भी रूपांतरण नहीं करना चाहते हैं, तो मैं बफ़र का सुझाव दूंगा। BLOCKCopy ()

 public static void BlockCopy( Array src, int srcOffset, Array dst, int dstOffset, int count ) 

उदाहरण के लिए:

 float[] floatArray = new float[1000]; byte[] byteArray = new byte[floatArray.Length * 4]; Buffer.BlockCopy(floatArray, 0, byteArray, 0, byteArray.Length); 

सभी बुराईयो की जड़ समयपूर्व इष्टतमीकरण है! @ वाल्द के प्रत्येक फ्लोट पर पुनरावृत्त करने के लिए सुझाव एक बाइट पर स्विच करने से अधिक उचित जवाब है [] तत्वों की संख्या बढ़ाने के लिए रनटाइम की निम्न तालिका लें (औसत 50 रन):

 Elements BinaryWriter(float) BinaryWriter(byte[]) ----------------------------------------------------------- 10 8.72ms 8.76ms 100 8.94ms 8.82ms 1000 10.32ms 9.06ms 10000 32.56ms 10.34ms 100000 213.28ms 739.90ms 1000000 1955.92ms 10668.56ms 

छोटी संख्या के तत्वों के लिए दोनों के बीच में थोड़ा अंतर होता है। एक बार जब आप बड़ी संख्या में तत्वों की श्रेणी में आते हैं, तो फ्लोट [] से बाइट [] तक नकल करने का समय बकाया लाभों से अधिक है

तो क्या सरल है के साथ जाओ:

 float[] data = new float[...]; foreach(float value in data) { writer.Write(value); } 

ऐसा करने का एक गंदे तेज (असुरक्षित कोड नहीं) तरीका है:

 [StructLayout(LayoutKind.Explicit)] struct BytetoDoubleConverter { [FieldOffset(0)] public Byte[] Bytes; [FieldOffset(0)] public Double[] Doubles; } //... static Double Sum(byte[] data) { BytetoDoubleConverter convert = new BytetoDoubleConverter { Bytes = data }; Double result = 0; for (int i = 0; i < convert.Doubles.Length / sizeof(Double); i++) { result += convert.Doubles[i]; } return result; } 

यह काम करेगा, लेकिन मैं मोनो या सीएलआर के नए संस्करणों के समर्थन के बारे में निश्चित नहीं हूं। केवल अजीब बात यह है कि array.Length । लंबाई बाइट्स लंबाई है इसे समझाया जा सकता है क्योंकि यह सरणी के साथ संग्रहीत सरणी लंबाई को दिखता है, और क्योंकि यह सरणी एक बाइट सरणी थी, वह लंबाई अभी भी बाइट लंबाई में होगी। इंडेक्टर के बारे में सोचता है कि डबल बाइट्स आठ बड़े हैं, इसलिए कोई गणना आवश्यक नहीं है।

मैंने इसके लिए कुछ और देखा है, और यह वास्तव में एमएसडीएन पर वर्णित है, कैसे करें: ए सी का उपयोग करके सी / सी ++ यूनियन बनाएँ (सी # और विज़ुअल बेसिक) , इतनी संभावनाएं भविष्य के संस्करणों में समर्थित होंगी। मैं हालांकि मोनो के बारे में निश्चित नहीं हूँ

एक तरीका है जो स्मृति प्रतिलिपि और पुनरावृत्ति से बचा जाता है।

(असुरक्षित) मेमोरी हेरफेर का उपयोग करके आप अपने सरणी को अस्थायी रूप से अस्थायी रूप से दूसरे प्रकार से बदल सकते हैं।

मैंने 32 और 64 बिट OS दोनों में इस हैक का परीक्षण किया है, इसलिए यह पोर्टेबल होना चाहिए।

स्रोत + नमूना उपयोग https://gist.github.com/1050703 पर बनाए रखा जाता है, लेकिन आपकी सुविधा के लिए मैं इसे यहाँ भी पेस्ट करूँगा:

 public static unsafe class FastArraySerializer { [StructLayout(LayoutKind.Explicit)] private struct Union { [FieldOffset(0)] public byte[] bytes; [FieldOffset(0)] public float[] floats; } [StructLayout(LayoutKind.Sequential, Pack = 1)] private struct ArrayHeader { public UIntPtr type; public UIntPtr length; } private static readonly UIntPtr BYTE_ARRAY_TYPE; private static readonly UIntPtr FLOAT_ARRAY_TYPE; static FastArraySerializer() { fixed (void* pBytes = new byte[1]) fixed (void* pFloats = new float[1]) { BYTE_ARRAY_TYPE = getHeader(pBytes)->type; FLOAT_ARRAY_TYPE = getHeader(pFloats)->type; } } public static void AsByteArray(this float[] floats, Action<byte[]> action) { if (floats.handleNullOrEmptyArray(action)) return; var union = new Union {floats = floats}; union.floats.toByteArray(); try { action(union.bytes); } finally { union.bytes.toFloatArray(); } } public static void AsFloatArray(this byte[] bytes, Action<float[]> action) { if (bytes.handleNullOrEmptyArray(action)) return; var union = new Union {bytes = bytes}; union.bytes.toFloatArray(); try { action(union.floats); } finally { union.floats.toByteArray(); } } public static bool handleNullOrEmptyArray<TSrc,TDst>(this TSrc[] array, Action<TDst[]> action) { if (array == null) { action(null); return true; } if (array.Length == 0) { action(new TDst[0]); return true; } return false; } private static ArrayHeader* getHeader(void* pBytes) { return (ArrayHeader*)pBytes - 1; } private static void toFloatArray(this byte[] bytes) { fixed (void* pArray = bytes) { var pHeader = getHeader(pArray); pHeader->type = FLOAT_ARRAY_TYPE; pHeader->length = (UIntPtr)(bytes.Length / sizeof(float)); } } private static void toByteArray(this float[] floats) { fixed(void* pArray = floats) { var pHeader = getHeader(pArray); pHeader->type = BYTE_ARRAY_TYPE; pHeader->length = (UIntPtr)(floats.Length * sizeof(float)); } } } 

और इसका उपयोग है:

 var floats = new float[] {0, 1, 0, 1}; floats.AsByteArray(bytes => { foreach (var b in bytes) { Console.WriteLine(b); } }); 

आप बेहतर कर रहे हैं द्विआधारी WRITER को यह आपके लिए करते हैं । आपके संपूर्ण डेटा सेट पर पुनरावृत्ति होने जा रहा है, भले ही आप किस पद्धति का उपयोग करें, इस प्रकार बाइट्स के साथ खेलने का कोई मतलब नहीं है।

यद्यपि आप एक byte* पॉइंटर को unsafe और fixed का उपयोग कर सकते हैं, तो आप byte* को byte[] परिवर्तित नहीं कर सकते हैं ताकि क्रिएटिव डेटा कॉपी किए बिना एक पैरामीटर के रूप में इसे स्वीकार कर सकते हैं। जो आप ऐसा नहीं करना चाहते क्योंकि यह आपकी मेमोरी पदचिह्न को दोगुना कर देगा और अपरिहार्य पुनरावृत्ति के ऊपर एक अतिरिक्त आवृत्ति जोड़ देगा जो डेटा को डिस्क पर आउटपुट करने के लिए किया जाना चाहिए।

इसके बजाए, आप अभी भी float की सरणी पर चलने से बेहतर होते हैं और प्रत्येक float को लेखक को व्यक्तिगत रूप से लिखे Write(double) पद्धति का उपयोग करके Write(double) । लेखक के अंदर बफरिंग की वजह से यह अभी भी तेजी से होगा sixlettervariables की संख्या देखें

हमारे पास एक क्लासिक है जिसे लूटिकसस्पीड सर्टिसाइज़ेशन कहा जाता है और इसमें निम्न असुरक्षित विधि होती है:

  static public byte[] ConvertFloatsToBytes(float[] data) { int n = data.Length; byte[] ret = new byte[n * sizeof(float)]; if (n == 0) return ret; unsafe { fixed (byte* pByteArray = &ret[0]) { float* pFloatArray = (float*)pByteArray; for (int i = 0; i < n; i++) { pFloatArray[i] = data[i]; } } } return ret; } 

हालांकि यह मूल रूप से पर्दे के पीछे लूप के लिए करता है, यह एक पंक्ति में काम करता है

 byte[] byteArray = floatArray.Select( f=>System.BitConverter.GetBytes(f)).Aggregate( (bytes, f) => {List<byte> temp = bytes.ToList(); temp.AddRange(f); return temp.ToArray(); });