MyCaffe  1.12.2.41
Deep learning software for Windows C# programmers.
Blob.cs
1using System;
2using System.Collections.Generic;
3using System.Linq;
4using System.Text;
5using System.IO;
6using System.Threading;
7using System.Diagnostics;
8using System.Drawing;
9using MyCaffe.param;
10using MyCaffe.basecode;
11using System.Drawing.Text;
12
13namespace MyCaffe.common
14{
24 public class Blob<T> : IDisposable
25 {
26 T m_tZero;
27 T m_tMinusOne;
28 string m_strName = "";
29 CudaDnn<T> m_cuda;
30 Log m_log;
31 bool m_bIncludeDiff = true;
32 bool m_bOwnData = true;
33 SyncedMemory<T> m_data = null;
34 bool m_bOwnDiff = true;
35 SyncedMemory<T> m_diff = null;
36 bool m_bOwnShape = true;
37 SyncedMemory<T> m_shape = null;
38 int m_nCount = 0;
39 int m_nCapacity = 0;
40 List<int> m_rgShape = new List<int>();
41 int m_nIdx = -1;
42 BLOB_TYPE m_type = BLOB_TYPE.DATA;
43 object m_tag = null;
44 bool m_bFreezeLearning = false;
45 bool m_bCpuDataReadyForPush = false;
46 bool m_bReshapeWhenSharing = false;
47 bool m_bSnapshotRequested = false;
48 bool m_bPadded = false;
49 Dictionary<string, double> m_rgParam = new Dictionary<string, double>();
50 int[] m_rgShape1 = new int[4] { 1, 1, 1, 1 };
51
55 public const int MAX_BLOB_AXES = 32;
56
64 public Blob(CudaDnn<T> cuda, Log log, bool bIncludeDiff = true, bool bUseHalfSize = false)
65 {
66 if (bUseHalfSize && typeof(T) != typeof(float))
67 {
68 bUseHalfSize = false;
69
70 if (log != null)
71 log.WriteLine("WARNING: Half sizes currently only supported with the 'float' base type - changing back to full size.");
72 }
73
74 m_tZero = Zero;
75 m_tMinusOne = MinusOne;
76 m_bIncludeDiff = bIncludeDiff;
77 m_cuda = cuda;
78 m_log = log;
79 m_shape = new SyncedMemory<T>(m_cuda, m_log);
80 m_data = new SyncedMemory<T>(m_cuda, m_log, 0, null, bUseHalfSize);
81
82 if (m_bIncludeDiff)
83 m_diff = new SyncedMemory<T>(m_cuda, m_log, 0, null, bUseHalfSize);
84 }
85
86
98 public Blob(CudaDnn<T> cuda, Log log, int nNum, int nChannels, int nHeight, int nWidth, bool bIncludeDiff = true, bool bUseHalfSize = false)
99 : this(cuda, log, bIncludeDiff, bUseHalfSize)
100 {
101 // Capacity must be initialized before calling Reshape.
102 m_nCapacity = 0;
103 Reshape(nNum, nChannels, nHeight, nWidth);
104 }
105
106
115 public Blob(CudaDnn<T> cuda, Log log, List<int> rgShape, bool bIncludeDiff = true, bool bUseHalfSize = false)
116 : this(cuda, log, bIncludeDiff, bUseHalfSize)
117 {
118 // Capacity must be initialized before calling Reshape.
119 m_nCapacity = 0;
120 Reshape(rgShape);
121 }
122
131 public Blob(CudaDnn<T> cuda, Log log, int[] rgShape, bool bIncludeDiff = true, bool bUseHalfSize = false)
132 : this(cuda, log, bIncludeDiff, bUseHalfSize)
133 {
134 // Capacity must be initialized before calling Reshape.
135 m_nCapacity = 0;
136 Reshape(rgShape);
137 }
138
146 public Blob(CudaDnn<T> cuda, Log log, Blob<T> b, bool bUseHalfSize = false)
147 : this(cuda, log, (b.m_diff != null) ? true : false, bUseHalfSize)
148 {
149 // Capacity must be initialized before calling Reshape.
150 m_nCapacity = 0;
151 ReshapeLike(b);
152 }
153
163 public Blob(CudaDnn<T> cuda, Log log, SimpleDatum d, bool bCopyData = false, bool bIncludeDiff = true, bool bUseHalfSize = false)
164 : this(cuda, log, bIncludeDiff, bUseHalfSize)
165 {
166 SetData(d, true, bCopyData);
167 }
168
176 public Blob(CudaDnn<T> cuda, Log log, BlobProto bp, bool bUseHalfSize = false)
177 : this(cuda, log, true, bUseHalfSize)
178 {
179 FromProto(bp);
180 }
181
188 public Blob(Blob<T> blob, long lCount, long lOffset)
189 : this(blob.Cuda, blob.Log, blob.m_bIncludeDiff)
190 {
191 m_data.set_gpu_data(blob.gpu_data, lCount, lOffset);
192
193 if (m_diff != null)
194 m_diff.set_gpu_data(blob.gpu_diff, lCount, lOffset);
195 }
196
201 public void Unsqueeze(int nNumAxes)
202 {
203 if (num_axes < 4)
204 {
205 List<int> rgShape = Utility.Clone<int>(shape());
206 for (int i = rgShape.Count; i < 4; i++)
207 {
208 rgShape.Add(1);
209 }
210
211 Reshape(rgShape);
212 }
213 }
214
220 public double? GetParameter(string strName)
221 {
222 if (m_rgParam.ContainsKey(strName))
223 return m_rgParam[strName];
224
225 return null;
226 }
227
233 public void SetParameter(string strName, double dfVal)
234 {
235 if (!m_rgParam.ContainsKey(strName))
236 m_rgParam.Add(strName, dfVal);
237 else
238 m_rgParam[strName] = dfVal;
239 }
240
245 public void CopyParameters(Blob<T> b)
246 {
247 foreach (KeyValuePair<string, double> kv in b.m_rgParam)
248 {
249 if (!m_rgParam.ContainsKey(kv.Key))
250 m_rgParam.Add(kv.Key, kv.Value);
251 else
252 m_rgParam[kv.Key] = kv.Value;
253 }
254 }
255
259 public static T Zero
260 {
261 get { return (T)Convert.ChangeType(0, typeof(T)); }
262 }
263
267 public static T One
268 {
269 get { return (T)Convert.ChangeType(1, typeof(T)); }
270 }
271
275 public static T MinusOne
276 {
277 get { return (T)Convert.ChangeType(-1, typeof(T)); }
278 }
279
283 public bool Padded
284 {
285 get { return m_bPadded; }
286 set { m_bPadded = value; }
287 }
288
293 public ulong GetConversionWorkSize(bool bUseHalfSize)
294 {
295 // (count (for data) + count (for diff)) * base type size
296 return (ulong)count() * 2 * CudaDnn<T>.basetype_size(bUseHalfSize);
297 }
298
306 public void ConvertToHalf(long hWorkMem, ulong lWorkSize, bool bData, bool bDiff)
307 {
308 int nCount = count();
309 ulong lSize = (ulong)nCount * 2 * CudaDnn<T>.basetype_size(true);
310
311 if ((long)lSize < 0)
312 throw new Exception("Memory out of range!");
313
314 if (lWorkSize < lSize)
315 throw new Exception("Work memory is not large enough!");
316
317 if (bData)
318 m_cuda.copy(nCount, gpu_data, hWorkMem, 0, 0, -1, null, true);
319
320 if (bDiff)
321 m_cuda.copy(nCount, gpu_diff, hWorkMem, 0, nCount, -1, null, true);
322
323 Reshape(shape(), true);
324
325 if (bData)
326 m_cuda.copy(nCount, hWorkMem, mutable_gpu_data, 0, 0, -1, true, null);
327
328 if (bDiff)
329 m_cuda.copy(nCount, hWorkMem, mutable_gpu_diff, nCount, 0, -1, true, null);
330 }
331
339 public void ConvertToBase(long hWorkMem, ulong lWorkSize, bool bData, bool bDiff)
340 {
341 int nCount = count();
342 ulong lSize = (ulong)nCount * 2 * CudaDnn<T>.basetype_size(false);
343
344 if ((long)lSize < 0)
345 throw new Exception("Memory out of range!");
346
347 if (lWorkSize < lSize)
348 throw new Exception("Work memory is not large enough!");
349
350 if (bData)
351 m_cuda.copy(nCount, gpu_data, hWorkMem, 0, 0, -1, null, false);
352
353 if (bDiff)
354 m_cuda.copy(nCount, gpu_diff, hWorkMem, 0, nCount, -1, null, false);
355
356 Reshape(shape(), false);
357
358 if (bData)
359 m_cuda.copy(nCount, hWorkMem, mutable_gpu_data, 0, 0, -1, false, null);
360
361 if (bDiff)
362 m_cuda.copy(nCount, hWorkMem, mutable_gpu_diff, nCount, 0, -1, false, null);
363 }
364
368 public bool HalfSize
369 {
370 get { return m_data.HalfSize; }
371 }
372
376 public bool freeze_learning
377 {
378 get { return m_bFreezeLearning; }
379 set { m_bFreezeLearning = value; }
380 }
381
386 {
387 get { return m_cuda; }
388 }
389
393 public Log Log
394 {
395 get { return m_log; }
396 }
397
402 protected virtual void Dispose(bool bDisposing)
403 {
404 if (m_diff != null)
405 {
406 if (m_bOwnDiff)
407 m_diff.Dispose();
408 m_diff = null;
409 }
410
411 if (m_data != null)
412 {
413 if (m_bOwnData)
414 m_data.Dispose();
415 m_data = null;
416 }
417
418 if (m_shape != null)
419 {
420 if (m_bOwnShape)
421 m_shape.Dispose();
422 m_shape = null;
423 }
424 }
425
429 public void Dispose()
430 {
431 Dispose(true);
432 }
433
442 public void Reshape(int nNum, int nChannels, int nHeight, int nWidth, bool? bUseHalfSize = null)
443 {
444 m_rgShape1[0] = nNum;
445 m_rgShape1[1] = nChannels;
446 m_rgShape1[2] = nHeight;
447 m_rgShape1[3] = nWidth;
448
449 Reshape(m_rgShape1, bUseHalfSize);
450 }
451
452 private string toString(List<int> rgShape)
453 {
454 return toString(rgShape.ToArray());
455 }
456
457 private string toString(int[] rgShape)
458 {
459 string str = "{";
460
461 for (int i = 0; i < rgShape.Length; i++)
462 {
463 str += rgShape[i].ToString();
464 str += ", ";
465 }
466
467 str = str.TrimEnd(' ', ',');
468 str += "}";
469
470 return str;
471 }
472
473 private void reshapeShape(List<int> rgShape)
474 {
475 reshapeShape(rgShape.ToArray());
476 }
477
478 private void reshapeShape(int[] rgShape)
479 {
480 m_log.CHECK_LE(rgShape.Length, MAX_BLOB_AXES, "The number of axes cannot exceed " + MAX_BLOB_AXES.ToString());
481 m_nCount = 1;
482
483 m_rgShape = new List<int>();
484
485 if (m_shape == null)
486 m_shape = new SyncedMemory<T>(m_cuda, m_log, rgShape.Length);
487 else if (m_shape.Capacity < rgShape.Length)
488 m_shape.Allocate(rgShape.Length);
489 else if (m_shape.Count != rgShape.Length)
490 {
491 m_shape.Count = rgShape.Length;
492 m_shape.ZeroAll();
493 }
494
495 if (rgShape.Length > 0)
496 {
497 T[] rgShapeData = m_shape.cpu_data;
498
499 if (rgShapeData == null || rgShapeData.Length != rgShape.Length)
500 {
501 rgShapeData = m_shape.update_cpu_data();
502
503 if (rgShapeData == null || rgShapeData.Length != rgShape.Length)
504 rgShapeData = new T[rgShape.Length];
505 }
506
507 bool bDirty = false;
508
509 for (int i = 0; i < rgShape.Length; i++)
510 {
511 if (rgShape[i] < 0)
512 {
513 string strBlobName = (!string.IsNullOrEmpty(m_strName)) ? "Blob '" + m_strName + "': " : "";
514 m_log.FAIL(strBlobName + "The shape value at " + i.ToString() + " of shape " + toString(rgShape) + " must be >= 0.");
515 }
516
517 if (m_nCount != 0)
518 {
519 if (rgShape[i] > int.MaxValue / m_nCount)
520 {
521 string strBlobName = (!string.IsNullOrEmpty(m_strName)) ? "Blob '" + m_strName + "': " : "";
522 m_log.FAIL(strBlobName + "The blob size at item " + i.ToString() + " of shape " + toString(rgShape) + " exceeds the maximum of " + (int.MaxValue / m_nCount).ToString() + "!");
523 }
524 }
525
526 m_nCount *= rgShape[i];
527 m_rgShape.Add(rgShape[i]);
528
529 int nShape = (int)(double)Convert.ChangeType(rgShapeData[i], typeof(double));
530
531 if (nShape != rgShape[i])
532 {
533 rgShapeData[i] = (T)Convert.ChangeType(rgShape[i], typeof(T));
534 bDirty = true;
535 }
536 }
537
538 if (bDirty)
539 {
540 m_shape.mutable_cpu_data = rgShapeData;
541 m_shape.update_cpu_data();
542 }
543 }
544 }
545
562 public void Reshape(List<int> rgShape, bool? bUseHalfSize = null)
563 {
564 Reshape(rgShape.ToArray(), bUseHalfSize);
565 }
566
583 public void Reshape(int[] rgShape, bool? bUseHalfSize = null)
584 {
585 reshapeShape(rgShape);
586
587 if (m_nCount > m_nCapacity || (m_data != null && m_nCount > m_data.Capacity) || (m_diff != null && m_nCount > m_diff.Capacity) || (m_data != null && bUseHalfSize.HasValue && m_data.HalfSize != bUseHalfSize.Value))
588 {
589 if (m_data != null)
590 m_data.Dispose();
591
592 if (m_diff != null)
593 m_diff.Dispose();
594
595 m_nCapacity = m_nCount;
596
597 if (m_data == null)
598 m_data = new SyncedMemory<T>(m_cuda, m_log, m_nCapacity, null, bUseHalfSize.GetValueOrDefault(false));
599 else
600 m_data.Allocate(m_nCapacity, bUseHalfSize.GetValueOrDefault(m_data.HalfSize));
601
602 if (m_bIncludeDiff)
603 {
604 if (m_diff == null)
605 m_diff = new SyncedMemory<T>(m_cuda, m_log, m_nCapacity, null, bUseHalfSize.GetValueOrDefault(false));
606 else
607 m_diff.Allocate(m_nCapacity, bUseHalfSize.GetValueOrDefault(m_data.HalfSize));
608 }
609 }
610
611 if (m_data.Count != m_nCount)
612 m_data.Count = m_nCount;
613
614 if (m_bIncludeDiff)
615 {
616 if (m_diff.Count != m_nCount)
617 m_diff.Count = m_nCount;
618 }
619 }
620
637 public void Reshape(BlobShape shape, bool? bUseHalfSize = null)
638 {
639 m_log.CHECK_LE(shape.dim.Count, MAX_BLOB_AXES, "The shape dimension must be less than " + MAX_BLOB_AXES.ToString());
640 Reshape(shape.dim, bUseHalfSize);
641 }
642
648 public void ReshapeLike(Blob<T> b, bool? bUseHalfSize = null)
649 {
650 Reshape(b.shape(), bUseHalfSize);
651 }
652
656 public string shape_string
657 {
658 get
659 {
660 string strOut = "";
661
662 for (int i = 0; i < m_rgShape.Count; i++)
663 {
664 strOut += m_rgShape[i].ToString() + " ";
665 }
666
667 strOut += "(" + m_rgShape.Count.ToString() + ")";
668 return strOut;
669 }
670 }
671
675 public bool DiffExists
676 {
677 get { return m_bIncludeDiff; }
678 }
679
684 public List<int> shape()
685 {
686 return m_rgShape;
687 }
688
696 public int shape(int nIdx)
697 {
698 return m_rgShape[CanonicalAxisIndex(nIdx)];
699 }
700
704 public int num_axes
705 {
706 get
707 {
708 return m_rgShape.Count;
709 }
710 }
711
715 public int num_true_axes
716 {
717 get
718 {
719 int nCount = 0;
720 bool bCount = false;
721
722 for (int i = m_rgShape.Count - 1; i >= 0; i--)
723 {
724 if (bCount || m_rgShape[i] != 1)
725 {
726 nCount++;
727 bCount = true;
728 }
729 }
730
731 return nCount;
732 }
733 }
734
739 public int count()
740 {
741 return m_nCount;
742 }
743
751 public int count(int nStartIdx, int nEndIdx)
752 {
753 m_log.CHECK_LE(nStartIdx, nEndIdx, "The start idx must be <= the end idx.");
754 m_log.CHECK_GE(nStartIdx, 0, "The start idx must be >= 0.");
755 m_log.CHECK_GE(nEndIdx, 0, "The end idx must be >= 0.");
756 m_log.CHECK_LE(nStartIdx, num_axes, "The start axis must be <= the number of axes.");
757 m_log.CHECK_LE(nEndIdx, num_axes, "The end axis must be <= the number of axes.");
758
759 return Utility.Count(shape(), nStartIdx, nEndIdx);
760 }
761
768 public int count(int nStartIdx)
769 {
770 return count(nStartIdx, num_axes);
771 }
772
780 public int CanonicalAxisIndex(int nIdx)
781 {
782 m_log.CHECK_GE(nIdx, -num_axes, "The axis " + nIdx.ToString() + " out of range for " + num_axes.ToString() + " -D Blob with shape " + shape_string);
783 m_log.CHECK_LT(nIdx, num_axes, "The axis " + nIdx.ToString() + " out of range for " + num_axes.ToString() + " -D Blob with shape " + shape_string);
784
785 return Utility.CanonicalAxisIndex(nIdx, num_axes);
786 }
787
791 public int num
792 {
793 get { return LegacyShape(0); }
794 }
795
799 public int channels
800 {
801 get { return LegacyShape(1); }
802 }
803
807 public int height
808 {
809 get { return LegacyShape(2); }
810 }
811
815 public int width
816 {
817 get { return LegacyShape(3); }
818 }
819
825 public int LegacyShape(int nIdx)
826 {
827 m_log.CHECK_LE(num_axes, 4, "Cannot use legacy accessors on Blobs with > 4 axes.");
828 m_log.CHECK_LT(nIdx, 4, "The index must be less than 4.");
829 m_log.CHECK_GE(nIdx, -4, "The index must be greater than or equal to -4.");
830
831 if (nIdx >= num_axes || nIdx < -num_axes)
832 {
833 // Axis is out of range, but still in [0,3] or [-4,-1] for reverse
834 // indexing) -- this special case simulates the one-padding used to fill
835 // extraneous axes of legacy blobs.
836 return 1;
837 }
838
839 return shape(nIdx);
840 }
841
850 public int offset(int n, int c = 0, int h = 0, int w = 0)
851 {
852 int c1 = channels;
853 int h1 = height;
854 int w1 = width;
855
856 m_log.CHECK_GE(n, 0, "n must be >= 0.");
857 m_log.CHECK_LE(n, num, "n must be <= num.");
858 m_log.CHECK_GE(c1, 0, "channels must be >= 0.");
859 m_log.CHECK_LE(c, c1, "c must be <= channels.");
860 m_log.CHECK_GE(h1, 0, "height must be >= 0.");
861 m_log.CHECK_LE(h, h1, "w must be <= height.");
862 m_log.CHECK_GE(w1, 0, "width must be >= 0.");
863 m_log.CHECK_LE(w, w1, "w must be <= width.");
864
865 return ((n * c1 + c) * h1 + h) * w1 + w;
866 }
867
873 public int offset(List<int> rgIdx)
874 {
875 m_log.CHECK_LE(rgIdx.Count, num_axes, "The index array must have an item count <= num_axes.");
876
877 int nOffset = 0;
878
879 for (int i = 0; i < num_axes; i++)
880 {
881 nOffset *= shape(i);
882
883 if (rgIdx.Count > i)
884 {
885 m_log.CHECK_GE(rgIdx[i], 0, "The index at " + i.ToString() + " must be >= 0.");
886 m_log.CHECK_LT(rgIdx[i], shape(i), "The index at " + i.ToString() + " must be <= the shape at " + i.ToString());
887 nOffset += rgIdx[i];
888 }
889 }
890
891 return nOffset;
892 }
893
903 public void CopyFrom(Blob<T> src, int nSrcOffset, int nDstOffset, int nCount, bool bCopyData, bool bCopyDiff)
904 {
905 m_log.CHECK_GE(count(), nDstOffset + nCount, "The data to be copied is larger that the destination blob.");
906 m_log.CHECK_GE(src.count(), nSrcOffset + nCount, "The data to be copied is larger than the source blob.");
907
908 if (bCopyData)
909 m_cuda.copy(nCount, src.gpu_data, mutable_gpu_data, nSrcOffset, nDstOffset);
910
911 if (bCopyDiff)
912 m_cuda.copy(nCount, src.gpu_diff, mutable_gpu_diff, nSrcOffset, nDstOffset);
913 }
914
928 public long CopyFrom(Blob<T> src, bool bCopyDiff = false, bool bReshape = false, long hDstHostBuffer = 0, bool bIgnoreShape = false)
929 {
930 // Ignore copy if the data points to the same handle.
931 if (bCopyDiff)
932 {
933 if (src.gpu_diff == gpu_diff)
934 return 0;
935 }
936 else
937 {
938 if (src.gpu_data == gpu_data)
939 return 0;
940 }
941
942 if (src.count() != m_nCount || (!bIgnoreShape && !CompareShape(src.m_rgShape)))
943 {
944 if (bReshape)
945 ReshapeLike(src);
946 else
947 m_log.FAIL("Trying to copy blobs of different sizes!");
948 }
949
950 if (bCopyDiff)
951 {
952 if (m_diff == null)
953 return hDstHostBuffer;
954
955 return m_diff.Copy(src.diff, hDstHostBuffer);
956 }
957 else
958 {
959 if (m_data == null)
960 return hDstHostBuffer;
961
962 return m_data.Copy(src.data, hDstHostBuffer);
963 }
964 }
965
973 public void CopyFromAndPad(Blob<T> src, double dfPad = 0, bool bCopyDiff = false)
974 {
975 if (count() == src.count())
976 {
977 CopyFrom(src, bCopyDiff);
978 return;
979 }
980
981 if (count() < src.count())
982 m_log.FAIL("The destination blob must be larger than the source blob.");
983
984 if (bCopyDiff)
985 {
986 SetDiff(dfPad);
987 m_cuda.copy(src.count(), src.gpu_diff, mutable_gpu_diff);
988 }
989 else
990 {
991 SetData(dfPad);
992 m_cuda.copy(src.count(), src.gpu_data, mutable_gpu_data);
993 }
994 }
995
1002 public void CopyFromAndTransposeHeightWidth(Blob<T> blobSrc, bool bCopyDiff = false, bool bUseCuda = true)
1003 {
1004 m_log.CHECK_EQ(blobSrc.num_axes, 4, "Currently, Blobs only support transposing 4 axis tensors.");
1005
1006 Reshape(blobSrc.num, blobSrc.channels, blobSrc.width, blobSrc.height);
1007
1008 SyncedMemory<T> dst = (bCopyDiff) ? m_diff : m_data;
1009 SyncedMemory<T> src = (bCopyDiff) ? blobSrc.m_diff : blobSrc.m_data;
1010
1011 int nN = num;
1012 int nC = channels;
1013 int nH = height;
1014 int nW = width;
1015
1016 if (bUseCuda)
1017 {
1018 m_cuda.transposeHW(nN, nC, nH, nW, src.gpu_data, dst.mutable_gpu_data);
1019 }
1020 else
1021 {
1022 T[] rgSrc = src.update_cpu_data();
1023 T[] rgDst = dst.mutable_cpu_data;
1024
1025 for (int n = 0; n < nN; n++)
1026 {
1027 for (int c = 0; c < nC; c++)
1028 {
1029 int nOffset = (n * nC * nH * nW) + (c * nH * nW);
1030
1031 for (int h = 0; h < nH; h++)
1032 {
1033 for (int w = 0; w < nW; w++)
1034 {
1035 int nSrcIdx = nOffset + (h * nW) + w;
1036 int nDstIdx = nOffset + (w + nH) + h;
1037 rgDst[nDstIdx] = rgSrc[nSrcIdx];
1038 }
1039 }
1040 }
1041 }
1042
1043 dst.mutable_cpu_data = rgDst;
1044 }
1045 }
1046
1054 public void CopyFrom(Blob<T> blobSrc, int nChannelFrom, int nChannelTo, bool bCopyDiff = false)
1055 {
1056 m_log.CHECK_EQ(blobSrc.num, num, "The source and destination blobs must have the same num.");
1057 m_log.CHECK_EQ(blobSrc.height, height, "The source and destination blobs must have the same height.");
1058 m_log.CHECK_EQ(blobSrc.width, width, "The source and destination blobs must have the same width.");
1059 m_log.CHECK_LT(nChannelFrom, blobSrc.channels, "The channel form parameter is out of range!");
1060 m_log.CHECK_LT(nChannelTo, channels, "The channel to parameter is out of range!");
1061
1062 SyncedMemory<T> dst = (bCopyDiff) ? m_diff : m_data;
1063 SyncedMemory<T> src = (bCopyDiff) ? blobSrc.m_diff : blobSrc.m_data;
1064
1065 int nCsrc = blobSrc.channels;
1066 int nCdst = channels;
1067 int nDim = height * width;
1068 int nSrcOffset = nChannelFrom * nDim;
1069 int nDstOffset = nChannelTo * nDim;
1070 int nSrcStep = (nCsrc * nDim);
1071 int nDstStep = (nCdst * nDim);
1072
1073 for (int n = 0; n < num; n++)
1074 {
1075 m_cuda.copy(nDim, src.gpu_data, dst.mutable_gpu_data, nSrcOffset, nDstOffset);
1076 nSrcOffset += nSrcStep;
1077 nDstOffset += nDstStep;
1078 }
1079 }
1080
1093 public bool Compare(Blob<T> other, Blob<T> work, bool bDiff = false, double dfTol = 1e-8, bool bZeroCheck = true, bool bFullCompare = false, bool bDetectNans = true, bool bForceOtherData = false)
1094 {
1095 double dfMin;
1096 double dfMax;
1097 return CompareEx(other, work, out dfMin, out dfMax, bDiff, dfTol, bZeroCheck, bFullCompare, bDetectNans, bForceOtherData);
1098 }
1099
1114 public bool CompareEx(Blob<T> other, Blob<T> work, out double dfMin, out double dfMax, bool bDiff = false, double dfTol = 1e-8, bool bZeroCheck = true, bool bFullCompare = false, bool bDetectNans = true, bool bForceOtherData = false)
1115 {
1116 dfMin = -1;
1117 dfMax = -1;
1118
1119 int nCount = count();
1120 if (nCount != other.count())
1121 return false;
1122
1123 if (nCount == 0)
1124 return true;
1125
1126 if (Cuda.KernelHandle != other.Cuda.KernelHandle)
1127 throw new Exception("The compare blob has a different Cuda Kernel Handles!");
1128
1129 if (Cuda.KernelHandle != work.Cuda.KernelHandle)
1130 throw new Exception("The work blob has a different Cuda Kernel Handle!");
1131
1132 work.ReshapeLike(this);
1133
1134 long h1 = (bDiff) ? gpu_diff : gpu_data;
1135 long h2 = (bDiff && !bForceOtherData) ? other.gpu_diff : other.gpu_data;
1136 long lPos;
1137
1138 m_cuda.sub(nCount, h1, h2, work.mutable_gpu_data);
1139 dfMin = m_cuda.min(nCount, work.gpu_data, out lPos, 0, work.mutable_gpu_diff);
1140 dfMax = m_cuda.max(nCount, work.gpu_data, out lPos, 0, work.mutable_gpu_diff);
1141
1142 if (Math.Abs(dfMin) > dfTol)
1143 return false;
1144
1145 if (dfMax > dfTol)
1146 return false;
1147
1148 if (bDetectNans)
1149 {
1150 Tuple<double, double, double, double> minmax1 = m_cuda.minmax(nCount, h1, work.gpu_data, work.gpu_diff, true);
1151 if (minmax1.Item3 > 0 || minmax1.Item4 > 0)
1152 return false;
1153
1154 Tuple<double, double, double, double> minmax2 = m_cuda.minmax(nCount, h2, work.gpu_data, work.gpu_diff, true);
1155 if (minmax2.Item3 > 0 || minmax2.Item4 > 0)
1156 return false;
1157 }
1158
1159 if (bZeroCheck)
1160 {
1161 double dfZero1 = m_cuda.asum_double(nCount, h1);
1162 double dfZero2 = m_cuda.asum_double(nCount, h2);
1163
1164 if ((dfZero1 == 0 && dfZero2 != 0) || (dfZero1 != 0 && dfZero2 == 0))
1165 return false;
1166 }
1167
1168 if (bFullCompare)
1169 {
1170 float[] rgf1 = Utility.ConvertVecF<T>((bDiff) ? mutable_cpu_diff : mutable_cpu_data);
1171 float[] rgf2 = Utility.ConvertVecF<T>((bDiff) ? other.mutable_cpu_diff : other.mutable_cpu_data);
1172 Dictionary<int, float> rgErr = new Dictionary<int, float>();
1173
1174 for (int i = 0; i < rgf1.Length; i++)
1175 {
1176 float f1 = rgf1[i];
1177 float f2 = rgf2[i];
1178 float fDiff = Math.Abs(f1 - f2);
1179
1180 if (fDiff > dfTol)
1181 rgErr.Add(i, fDiff);
1182 }
1183
1184 if (rgErr.Count > 0)
1185 return false;
1186 }
1187
1188 return true;
1189 }
1190
1197 public bool ValidateData(Blob<T> work, bool bDiff = false)
1198 {
1199 int nCount = count();
1200 long h1 = (bDiff) ? gpu_diff : gpu_data;
1201
1202 work.ReshapeLike(this);
1203
1204 Tuple<double, double, double, double> minmax1 = m_cuda.minmax(nCount, h1, work.gpu_data, work.gpu_diff, true);
1205 if (minmax1.Item3 > 0 || minmax1.Item4 > 0)
1206 return false;
1207
1208 return true;
1209 }
1210
1220 public bool Compare(CudaDnn<double> cuda, Blob<T> other, Blob<double> work, bool bDiff = false, double dfTol = 1e-8)
1221 {
1222 if (count() != other.count())
1223 return false;
1224
1225 work.Reshape(num, channels, height, width);
1228
1229 cuda.sub(count(), work.gpu_data, work.gpu_diff, work.mutable_gpu_data);
1230 double dfMin = work.min_data;
1231 if (Math.Abs(dfMin) > dfTol)
1232 return false;
1233
1234 double dfMax = work.max_data;
1235 if (dfMax > dfTol)
1236 return false;
1237
1238 return true;
1239 }
1240
1241#pragma warning disable 1591
1242
1243 public void KeepBestResultsByChannel(int nNumberToKeep)
1244 {
1245 m_log.CHECK_EQ(num_axes, 4, "Currently KeepBestResutls only works on 4-axis blobs.");
1246
1247 T[] rgData = mutable_cpu_data;
1248 int nN = num;
1249 int nC = channels;
1250 int nH = height;
1251 int nW = width;
1252 List<List<KeyValuePair<int, float>>> rgrgKeyValues = new List<List<KeyValuePair<int, float>>>();
1253 List<List<List<List<float>>>> rgrgrgrgData = new List<List<List<List<float>>>>();
1254
1255 for (int n = 0; n < nN; n++)
1256 {
1257 List<KeyValuePair<int, float>> rgKeyValues = new List<KeyValuePair<int, float>>();
1258 List<List<List<float>>> rgrgrgData = new List<List<List<float>>>();
1259
1260 for (int c = 0; c < nC; c++)
1261 {
1262 float fSum = 0;
1263 List<List<float>> rgrgData = new List<List<float>>();
1264
1265 for (int h = 0; h < nH; h++)
1266 {
1267 List<float> rgVal = new List<float>();
1268
1269 for (int w = 0; w < nW; w++)
1270 {
1271 int nIdx = (n * nC * nH * nW) + (c * nH * nW) + (h * nW) + w;
1272 float fVal = (float)Convert.ChangeType(rgData[nIdx], typeof(float));
1273 rgVal.Add(fVal);
1274 fSum += fVal;
1275 }
1276
1277 rgrgData.Add(rgVal);
1278 }
1279
1280 rgKeyValues.Add(new KeyValuePair<int, float>(c, fSum));
1281 rgrgrgData.Add(rgrgData);
1282 }
1283
1284 rgKeyValues.Sort(new Comparison<KeyValuePair<int, float>>(sort));
1285
1286 rgrgKeyValues.Add(rgKeyValues);
1287 rgrgrgrgData.Add(rgrgrgData);
1288 }
1289
1290 SetData(0);
1291 rgData = mutable_cpu_data;
1292
1293 for (int n = 0; n < nN; n++)
1294 {
1295 List<KeyValuePair<int, float>> rgKeyValues = rgrgKeyValues[n];
1296 List<List<List<float>>> rgrgrgData = rgrgrgrgData[n];
1297 List<int> rgIdx = new List<int>();
1298
1299 for (int i = 0; i < nNumberToKeep && i < rgKeyValues.Count; i++)
1300 {
1301 rgIdx.Add(rgKeyValues[i].Key);
1302 }
1303
1304 foreach (int c in rgIdx)
1305 {
1306 List<List<float>> rgrgData = rgrgrgData[c];
1307
1308 for (int h = 0; h < nH; h++)
1309 {
1310 List<float> rgVal = rgrgData[h];
1311
1312 for (int w = 0; w < nW; w++)
1313 {
1314 int nIdx = (n * nC * nH * nW) + (c * nH * nW) + (h * nW) + w;
1315 rgData[nIdx] = (T)Convert.ChangeType(rgVal[w], typeof(T));
1316 }
1317 }
1318 }
1319 }
1320
1321 mutable_cpu_data = rgData;
1322 }
1323
1324 public void KeepBestResultsByWeight(int nNumberToKeep)
1325 {
1326 m_log.CHECK_EQ(num_axes, 4, "Currently KeepBestResutls only works on 4-axis blobs.");
1327
1328 T[] rgData = mutable_cpu_data;
1329 int nN = num;
1330 int nC = channels;
1331 int nH = height;
1332 int nW = width;
1333 List<List<KeyValuePair<int, float>>> rgrgKeyValues = new List<List<KeyValuePair<int, float>>>();
1334
1335 for (int n = 0; n < nN; n++)
1336 {
1337 List<KeyValuePair<int, float>> rgKeyValues = new List<KeyValuePair<int, float>>();
1338
1339 for (int c = 0; c < nC; c++)
1340 {
1341 for (int h = 0; h < nH; h++)
1342 {
1343 for (int w = 0; w < nW; w++)
1344 {
1345 int nIdx = (n * nC * nH * nW) + (c * nH * nW) + (h * nW) + w;
1346 rgKeyValues.Add(new KeyValuePair<int, float>(nIdx, (float)Convert.ChangeType(rgData[nIdx], typeof(float))));
1347 }
1348 }
1349 }
1350
1351 rgKeyValues.Sort(new Comparison<KeyValuePair<int, float>>(sort));
1352 rgrgKeyValues.Add(rgKeyValues);
1353 }
1354
1355 SetData(0);
1356 rgData = mutable_cpu_data;
1357
1358 for (int n = 0; n < nN; n++)
1359 {
1360 List<KeyValuePair<int, float>> rgKeyValues = rgrgKeyValues[n];
1361
1362 for (int i = 0; i < nNumberToKeep && i < rgKeyValues.Count; i++)
1363 {
1364 KeyValuePair<int, float> kv = rgKeyValues[i];
1365 rgData[kv.Key] = (T)Convert.ChangeType(kv.Value, typeof(T));
1366 }
1367 }
1368
1369 mutable_cpu_data = rgData;
1370 }
1371
1372#pragma warning restore 1591
1373
1374
1375 private int sort(KeyValuePair<int, float> a, KeyValuePair<int, float> b)
1376 {
1377 if (a.Value < b.Value)
1378 return 1;
1379
1380 if (a.Value > b.Value)
1381 return -1;
1382
1383 return 0;
1384 }
1385
1394 public T data_at(int n, int c, int h, int w)
1395 {
1396 return m_data.GetAt(offset(n, c, h, w));
1397 }
1398
1407 public T diff_at(int n, int c, int h, int w)
1408 {
1409 return m_diff.GetAt(offset(n, c, h, w));
1410 }
1411
1417 public T data_at(List<int> rgIdx)
1418 {
1419 return m_data.GetAt(offset(rgIdx));
1420 }
1421
1427 public T diff_at(List<int> rgIdx)
1428 {
1429 return m_diff.GetAt(offset(rgIdx));
1430 }
1431
1436 {
1437 get { return m_data; }
1438 }
1439
1444 {
1445 get { return m_diff; }
1446 }
1447
1451 public T[] cpu_data
1452 {
1453 get { return m_data.cpu_data; }
1454 }
1455
1461 {
1462 get { return m_data.mutable_cpu_data; }
1463 set { m_data.mutable_cpu_data = value; }
1464 }
1465
1470 public T[] update_cpu_data()
1471 {
1472 return m_data.update_cpu_data(m_nCount);
1473 }
1474
1478 public long gpu_data
1479 {
1480 get { return m_data.gpu_data; }
1481 }
1482
1487 {
1488 get { return m_data.mutable_gpu_data; }
1489// set { m_data.mutable_gpu_data = value; }
1490 }
1491
1495 public T[] cpu_diff
1496 {
1497 get
1498 {
1499 if (m_diff == null)
1500 return null;
1501
1502 return m_diff.cpu_data;
1503 }
1504 }
1505
1511 {
1512 get
1513 {
1514 if (m_diff == null)
1515 return null;
1516
1517 return m_diff.mutable_cpu_data;
1518 }
1519 set
1520 {
1521 m_diff.mutable_cpu_data = value;
1522 }
1523 }
1524
1529 public T[] update_cpu_diff()
1530 {
1531 if (m_diff == null)
1532 return null;
1533
1534 return m_diff.update_cpu_data(m_nCount);
1535 }
1536
1540 public long gpu_diff
1541 {
1542 get
1543 {
1544 if (m_diff == null)
1545 return 0;
1546
1547 return m_diff.gpu_data;
1548 }
1549 }
1550
1555 {
1556 get { return m_diff.mutable_gpu_data; }
1557// set { m_diff.mutable_gpu_data = value; }
1558 }
1559
1564 public long gpu_shape
1565 {
1566 get { return m_shape.gpu_data; }
1567 }
1568
1575 public void Update()
1576 {
1577 if (!m_bIncludeDiff || m_bFreezeLearning)
1578 return;
1579
1580 // The GPU is assumed to be the owner of the data.
1581 m_cuda.axpy(m_nCount, m_tMinusOne, m_diff.gpu_data, m_data.mutable_gpu_data);
1582 }
1583
1589 public void FromProto(BlobProto bp, bool bReshape = true)
1590 {
1591 if (bReshape)
1592 {
1593 List<int> rgShape = new List<int>();
1594
1595 if (bp.num.HasValue || bp.channels.HasValue || bp.height.HasValue || bp.width.HasValue)
1596 {
1597 // Using depreciated 4D Blob dimensions --
1598 // shape is (num, channels, height, width).
1599 if (bp.num.HasValue)
1600 rgShape.Add(bp.num.Value);
1601
1602 if (bp.channels.HasValue)
1603 rgShape.Add(bp.channels.Value);
1604
1605 if (bp.height.HasValue)
1606 rgShape.Add(bp.height.Value);
1607
1608 if (bp.width.HasValue)
1609 rgShape.Add(bp.width.Value);
1610 }
1611 else
1612 {
1613 rgShape = Utility.Clone<int>(bp.shape.dim);
1614 }
1615
1616 Reshape(rgShape);
1617 }
1618 else
1619 {
1620 m_log.CHECK(ShapeEquals(bp), "Shape mismatch (reshape not set)!");
1621 }
1622
1623 // Copy the data.
1624 T[] rgData = null;
1625
1626 if (bp.double_data.Count > 0)
1627 {
1628 m_log.CHECK_EQ(m_nCount, bp.double_data.Count, "The double data count is not the same as the blob data count!");
1629 rgData = Utility.ConvertVec<T>(bp.double_data.ToArray());
1630 }
1631 else if (bp.data.Count > 0)
1632 {
1633 m_log.CHECK_EQ(m_nCount, bp.data.Count, "The double data count is not the same as the blob data count!");
1634 rgData = Utility.ConvertVec<T>(bp.data.ToArray());
1635 }
1636
1637 if (rgData != null)
1638 mutable_cpu_data = rgData;
1639
1640 // Copy the diff.
1641 T[] rgDiff = null;
1642
1643 if (bp.double_diff.Count > 0)
1644 {
1645 m_log.CHECK_EQ(m_nCount, bp.double_diff.Count, "The double diff count is not the same as the blob data count!");
1646 rgDiff = Utility.ConvertVec<T>(bp.double_diff.ToArray());
1647 }
1648 else if (bp.diff.Count > 0)
1649 {
1650 m_log.CHECK_EQ(m_nCount, bp.diff.Count, "The double data count is not the same as the blob data count!");
1651 rgDiff = Utility.ConvertVec<T>(bp.diff.ToArray());
1652 }
1653
1654 if (rgDiff != null)
1655 mutable_cpu_diff = rgDiff;
1656 }
1657
1663 public BlobProto ToProto(bool bWriteDiff = false)
1664 {
1665 BlobProto bp = new BlobProto(m_rgShape);
1666
1667 T[] rgData = (bWriteDiff) ? null : update_cpu_data();
1668 T[] rgDiff = (bWriteDiff) ? update_cpu_diff() : null;
1669
1670 if (typeof(T) == typeof(double))
1671 {
1672 if (rgData != null)
1673 {
1674 double[] rgDataD = Utility.ConvertVec<T>(rgData);
1675 bp.double_data = new List<double>(rgDataD);
1676 }
1677
1678 if (rgDiff != null)
1679 {
1680 double[] rgDiffD = Utility.ConvertVec<T>(rgData);
1681 bp.double_diff = new List<double>(rgDiffD);
1682 }
1683 }
1684 else
1685 {
1686 if (rgData != null)
1687 {
1688 float[] rgDataF = Utility.ConvertVecF<T>(rgData);
1689 bp.data = new List<float>(rgDataF);
1690 }
1691
1692 if (rgDiff != null)
1693 {
1694 float[] rgDiffF = Utility.ConvertVecF<T>(rgDiff);
1695 bp.diff = new List<float>(rgDiffF);
1696 }
1697 }
1698
1699 return bp;
1700 }
1701
1706 public T asum_data()
1707 {
1708 if (m_nCount == 0 || gpu_data == 0)
1709 return m_tZero;
1710
1711 return m_cuda.asum(m_nCount, gpu_data);
1712 }
1713
1718 public T asum_diff()
1719 {
1720 if (m_nCount == 0 || gpu_diff == 0)
1721 return m_tZero;
1722
1723 return m_cuda.asum(m_nCount, gpu_diff);
1724 }
1725
1730 public T sumsq_data()
1731 {
1732 if (m_nCount == 0 || gpu_data == 0)
1733 return m_tZero;
1734
1735 return m_cuda.dot(m_nCount, gpu_data, gpu_data);
1736 }
1737
1742 public T sumsq_diff()
1743 {
1744 if (m_nCount == 0 || gpu_diff == 0)
1745 return m_tZero;
1746
1747 return m_cuda.dot(m_nCount, gpu_diff, gpu_diff);
1748 }
1749
1754 public void scale_data(double df)
1755 {
1756 scale_data((T)Convert.ChangeType(df, typeof(T)));
1757 }
1758
1763 public void scale_diff(double df)
1764 {
1765 scale_diff((T)Convert.ChangeType(df, typeof(T)));
1766 }
1767
1773 public void scale_to_range(double dfMin, double dfMax)
1774 {
1775 m_cuda.scale_to_range(m_nCount, gpu_data, mutable_gpu_data, dfMin, dfMax);
1776 }
1777
1782 public void scale_data(T fScaleFactor)
1783 {
1784 m_cuda.scal(m_nCount, fScaleFactor, mutable_gpu_data);
1785 }
1786
1791 public void scale_diff(T fScaleFactor)
1792 {
1793 m_cuda.scal(m_nCount, fScaleFactor, mutable_gpu_diff);
1794 }
1795
1803 {
1804 get { return m_bReshapeWhenSharing; }
1805 set { m_bReshapeWhenSharing = value; }
1806 }
1807
1813 public void ShareData(Blob<T> b)
1814 {
1815 if (!m_bReshapeWhenSharing)
1816 m_log.CHECK_EQ(m_nCount, b.count(), "The blob counts are not the same!");
1817 else
1818 reshapeShape(b.shape());
1819
1820 if (m_bOwnData && m_data != null)
1821 m_data.Dispose();
1822
1823 m_data = b.m_data;
1824 m_bOwnData = false;
1825 }
1826
1832 public void ShareDiff(Blob<T> b)
1833 {
1834 if (!m_bReshapeWhenSharing)
1835 m_log.CHECK_EQ(m_nCount, b.count(), "The blob counts are not the same!");
1836 else
1837 reshapeShape(b.shape());
1838
1839 if (m_bOwnDiff && m_diff != null)
1840 m_diff.Dispose();
1841
1842 m_diff = b.m_diff;
1843 m_bOwnDiff = false;
1844 }
1845
1850 public void Share(Blob<T> b)
1851 {
1852 if (m_bOwnData && m_data != null)
1853 m_data.Dispose();
1854
1855 m_data = b.m_data;
1856 m_bOwnData = false;
1857
1858 if (m_bOwnDiff && m_diff != null)
1859 m_diff.Dispose();
1860
1861 m_diff = b.m_diff;
1862 m_bOwnDiff = false;
1863
1864 if (m_bOwnShape && m_shape != null)
1865 m_shape.Dispose();
1866
1867 m_shape = b.m_shape;
1868 m_bOwnShape = false;
1869
1870 m_nCount = b.m_nCount;
1871 m_nCapacity = b.m_nCapacity;
1872 m_rgShape = b.m_rgShape;
1873 m_nIdx = b.m_nIdx;
1874 }
1875
1883 {
1884 get { return m_bSnapshotRequested; }
1885 set { m_bSnapshotRequested = value; }
1886 }
1887
1893 public T GetData(int nIdx)
1894 {
1895 T[] rg = m_cuda.get(count(), gpu_data, nIdx);
1896 if (rg.Length == 0)
1897 throw new Exception("No data at index = " + nIdx.ToString());
1898
1899 return rg[0];
1900 }
1901
1907 public T GetDiff(int nIdx)
1908 {
1909 T[] rg = m_cuda.get(count(), gpu_diff, nIdx);
1910 if (rg.Length == 0)
1911 throw new Exception("No data at index = " + nIdx.ToString());
1912
1913 return rg[0];
1914 }
1915
1922 public void SetData(T[] rgData, int nCount = -1, bool bSetCount = true)
1923 {
1924 m_data.SetData(rgData, nCount, bSetCount);
1925 }
1926
1933 public void SetData(T fVal, int nIdx = -1)
1934 {
1935 if (mutable_gpu_data == 0)
1936 return;
1937
1938 m_cuda.set(count(), mutable_gpu_data, fVal, nIdx);
1939 }
1940
1947 public void SetData(double dfVal, int nIdx = -1)
1948 {
1949 if (mutable_gpu_data == 0)
1950 return;
1951
1952 m_cuda.set(count(), mutable_gpu_data, dfVal, nIdx);
1953 }
1954
1961 public void SetData(double dfVal, int nStartIdx, int nCount)
1962 {
1963 T tVal = (T)Convert.ChangeType(dfVal, typeof(T));
1964 T[] rg = mutable_cpu_data;
1965
1966 for (int i = 0; i < nCount; i++)
1967 {
1968 if (nStartIdx + i < rg.Length)
1969 rg[nStartIdx + i] = tVal;
1970 }
1971
1972 mutable_cpu_data = rg;
1973 }
1974
1981 public void SetDiff(double dfVal, int nIdx = -1)
1982 {
1983 if (m_bIncludeDiff)
1984 {
1985 if (mutable_gpu_diff == 0)
1986 return;
1987
1988 m_cuda.set(count(), mutable_gpu_diff, dfVal, nIdx);
1989 }
1990 }
1991
1998 public void SetDiff(double dfVal, int nStartIdx, int nCount)
1999 {
2000 T tVal = (T)Convert.ChangeType(dfVal, typeof(T));
2001 T[] rg = mutable_cpu_diff;
2002
2003 for (int i = 0; i < nCount; i++)
2004 {
2005 if (nStartIdx + i < rg.Length)
2006 rg[nStartIdx + i] = tVal;
2007 }
2008
2009 mutable_cpu_diff = rg;
2010 }
2011
2018 public void SetDiff(T[] rgDiff, int nCount = -1, bool bSetCount = true)
2019 {
2020 m_diff.SetData(rgDiff, nCount, bSetCount);
2021 }
2022
2029 public void SetData(SimpleDatum d, bool bReshape, bool bCopyData = true)
2030 {
2031 if (bReshape)
2032 {
2033 m_nCapacity = 0;
2034 Reshape(1, d.Channels, d.Height, d.Width);
2035 }
2036
2037 T[] rgData = d.GetData<T>();
2038
2039 m_log.CHECK_EQ(rgData.Length, count(), "The datum data length of " + rgData.Length.ToString() + " should be equal to the Blob count() of " + count().ToString());
2040
2041 if (bCopyData)
2042 {
2043 mutable_cpu_data = rgData;
2044 m_nIdx = d.Index;
2045 }
2046 }
2047
2052 public void SetCPUData(T[] rg)
2053 {
2054 m_bCpuDataReadyForPush = true;
2055 m_data.set_cpu_data_locally(rg);
2056 }
2057
2062 public void AsyncGpuPush(long hStream)
2063 {
2064 if (!m_bCpuDataReadyForPush)
2065 return;
2066
2067 if (m_data.cpu_data == null)
2068 throw new Exception("There is no CPU data to push to the GPU!");
2069
2070 m_data.async_gpu_push(hStream, m_data.cpu_data);
2071 m_bCpuDataReadyForPush = false;
2072 }
2073
2079 public bool ShapeEquals(BlobProto bp)
2080 {
2081 if (bp.num.HasValue || bp.channels.HasValue || bp.height.HasValue || bp.width.HasValue)
2082 {
2083 // Using drepreciated 4D blob dimensions --
2084 // shape is (num, channels, height, width).
2085 // Note: we do not use the normal Blob::num, Blob::channels() etc.
2086 // methods as these index from the beginning of the blob shape, where legacy
2087 // parameter blobs were indexed from the end of the blob shape (e.g., bias
2088 // Blob shape (1 x 1 x 1 x N), IP layer weight Blob shape (1 x 1 x M x N).
2089 if (m_rgShape.Count <= 4 &&
2090 LegacyShape(-4) == bp.num.GetValueOrDefault(1) &&
2091 LegacyShape(-3) == bp.channels.GetValueOrDefault(1) &&
2092 LegacyShape(-2) == bp.height.GetValueOrDefault(1) &&
2093 LegacyShape(-1) == bp.width.GetValueOrDefault(1))
2094 return true;
2095 else
2096 return false;
2097 }
2098
2099 return Utility.Compare<int>(m_rgShape, bp.shape.dim);
2100 }
2101
2108 public bool CompareShape(List<int> rgShape, bool bCompareCpuDataLen = false)
2109 {
2110 while (rgShape.Count < num_axes)
2111 {
2112 rgShape.Add(1);
2113 }
2114
2115 if (shape().Count == 0 && rgShape.Count == 0)
2116 return true;
2117
2118 if (shape().Count == 0 && rgShape.Count == 1 && rgShape[0] == 0)
2119 return true;
2120
2121 List<int> rgShape1 = new List<int>(shape());
2122 while (rgShape1.Count < rgShape.Count)
2123 {
2124 rgShape1.Add(1);
2125 }
2126
2127 if (bCompareCpuDataLen)
2128 {
2129 int nCount = 1;
2130 for (int i = 0; i < rgShape.Count; i++)
2131 {
2132 nCount *= rgShape[i];
2133 }
2134
2135 if (cpu_data == null || cpu_data.Length != nCount)
2136 return false;
2137 }
2138
2139 return Utility.Compare<int>(rgShape1, rgShape);
2140 }
2141
2148 public bool CompareShape(int[] rgShape, bool bCompareCpuDataLen = false)
2149 {
2150 return CompareShape(new List<int>(rgShape), bCompareCpuDataLen);
2151 }
2152
2157 public string ToSizeString()
2158 {
2159 return num.ToString() + "," + channels.ToString() + "," + height.ToString() + "," + width.ToString();
2160 }
2161
2167 {
2168 if (typeof(T) == typeof(double))
2169 {
2170 double[] rgData = m_cuda.GetMemoryDouble(gpu_data, count());
2171 return new Datum(true, channels, width, height, -1, DateTime.MinValue, new List<double>(rgData), 0, false, -1);
2172 }
2173 else
2174 {
2175 float[] rgData = m_cuda.GetMemoryFloat(gpu_data, count());
2176 return new Datum(true, channels, width, height, -1, DateTime.MinValue, new List<float>(rgData), 0, false, -1);
2177 }
2178 }
2179
2183 public string Name
2184 {
2185 get { return m_strName; }
2186 set
2187 {
2188 m_strName = value;
2189
2190 if (m_data != null)
2191 m_data.Tag = m_strName + " data";
2192
2193 if (m_diff != null)
2194 m_diff.Tag = m_strName + " diff";
2195 }
2196 }
2197
2203 {
2204 Blob<T> b = new Blob<T>(m_cuda, m_log);
2205
2206 b.ReshapeLike(this, HalfSize);
2207
2208 if (m_diff != null)
2209 b.m_diff.Copy(m_diff);
2210
2211 b.m_data.Copy(m_data);
2212 b.Name = Name;
2213 b.m_bReshapeWhenSharing = reshape_when_sharing;
2214
2215 return b;
2216 }
2217
2227 public Blob<T> MathAdd(Blob<T> blobA, T fScale)
2228 {
2229 Blob<T> bOut = blobA.Clone();
2230
2231 if ((double)Convert.ChangeType(fScale, typeof(double)) != 1.0)
2232 bOut.scale_data(fScale);
2233
2234 m_cuda.add(bOut.count(), bOut.gpu_data, gpu_data, bOut.mutable_gpu_data);
2235
2236 return bOut;
2237 }
2238
2248 {
2249 Blob<T> bOut = blobA.Clone();
2250
2251 m_cuda.sub(bOut.count(), bOut.gpu_data, gpu_data, bOut.mutable_gpu_data);
2252
2253 return bOut;
2254 }
2255
2264 public Blob<T> MathDiv(T fScale)
2265 {
2266 Blob<T> bOut = Clone();
2267
2268 double dfVal = 1.0/(double)Convert.ChangeType(fScale, typeof(double));
2269
2270 m_cuda.mul_scalar(bOut.count(), (T)Convert.ChangeType(dfVal, typeof(T)), bOut.mutable_gpu_data);
2271
2272 return bOut;
2273 }
2274
2282 public void SaveBinary(string strFile, bool bData, bool bDiff, bool bIncludeName = true)
2283 {
2284 using (FileStream fs = File.OpenWrite(strFile))
2285 using (BinaryWriter bw = new BinaryWriter(fs))
2286 {
2287 Save(bw, bData, bDiff, bIncludeName);
2288 }
2289 }
2290
2298 public void Save(BinaryWriter bw, bool bData, bool bDiff, bool bIncludeName = true)
2299 {
2300 if (!bIncludeName)
2301 {
2302 bw.Write(0);
2303 }
2304 else
2305 {
2306 bw.Write(m_strName.Length);
2307 bw.Write(m_strName);
2308 }
2309
2310 bw.Write(m_rgShape.Count);
2311 for (int i = 0; i < m_rgShape.Count; i++)
2312 {
2313 bw.Write(m_rgShape[i]);
2314 }
2315
2316 bw.Write(m_nCount);
2317
2318 if (bData)
2319 {
2320 bw.Write(m_nCount);
2321
2322 double[] rgdfData = Utility.ConvertVec<T>(update_cpu_data());
2323
2324 foreach (double dfVal in rgdfData)
2325 {
2326 bw.Write(dfVal);
2327 }
2328 }
2329 else
2330 {
2331 bw.Write((int)0);
2332 }
2333
2334 if (bDiff)
2335 {
2336 bw.Write(m_nCount);
2337
2338 double[] rgdfDiff = Utility.ConvertVec<T>(update_cpu_diff());
2339
2340 foreach (double dfVal in rgdfDiff)
2341 {
2342 bw.Write(dfVal);
2343 }
2344 }
2345 else
2346 {
2347 bw.Write((int)0);
2348 }
2349 }
2350
2359 public static Blob<T> LoadBinary(CudaDnn<T> cuda, Log log, string strFile, bool bData, bool bDiff)
2360 {
2361 using (FileStream fs = File.OpenRead(strFile))
2362 using (BinaryReader br = new BinaryReader(fs))
2363 {
2364 return Load(cuda, log, br, bData, bDiff);
2365 }
2366 }
2367
2377 public static Blob<T> Load(CudaDnn<T> cuda, Log log, BinaryReader br, bool bData, bool bDiff)
2378 {
2379 Blob<T> b = new Blob<T>(cuda, log);
2380
2381 int nNameLen = br.ReadInt32();
2382 if (nNameLen > 0)
2383 b.Name = br.ReadString();
2384
2385 List<int> rgShape = new List<int>();
2386 int nCount = br.ReadInt32();
2387
2388 for (int i = 0; i < nCount; i++)
2389 {
2390 rgShape.Add(br.ReadInt32());
2391 }
2392
2393 b.Reshape(rgShape);
2394
2395 int nItemCount = br.ReadInt32();
2396 int nDataCount = br.ReadInt32();
2397
2398 if (nDataCount > nItemCount)
2399 throw new Exception("Invalid data count read!");
2400
2401 List<double> rgData = new List<double>();
2402
2403 for (int i = 0; i < nDataCount; i++)
2404 {
2405 rgData.Add(br.ReadDouble());
2406 }
2407
2408 int nDiffCount = br.ReadInt32();
2409
2410 if (nDiffCount > nItemCount)
2411 throw new Exception("Invalid diff count read!");
2412
2413 List<double> rgDiff = new List<double>();
2414
2415 for (int i = 0; i < nDiffCount; i++)
2416 {
2417 rgDiff.Add(br.ReadDouble());
2418 }
2419
2420 if (nDataCount > 0 && nDiffCount > 0 && nDataCount != nDiffCount)
2421 throw new Exception("Invalid diff and data counts read - they should be equal!");
2422
2423 if (bData && rgData.Count > 0)
2424 b.mutable_cpu_data = Utility.ConvertVec<T>(rgData.ToArray());
2425
2426 if (bDiff && rgDiff.Count > 0)
2427 b.mutable_cpu_diff = Utility.ConvertVec<T>(rgDiff.ToArray());
2428
2429 return b;
2430 }
2431
2436 public byte[] ToByteArray()
2437 {
2438 using (MemoryStream ms = new MemoryStream())
2439 using (BinaryWriter bw = new BinaryWriter(ms))
2440 {
2441 Save(bw, true, false, true);
2442 return ms.ToArray();
2443 }
2444 }
2445
2453 public static Blob<T> FromByteArray(CudaDnn<T> cuda, Log log, byte[] rg)
2454 {
2455 using (MemoryStream ms = new MemoryStream(rg))
2456 using (BinaryReader br = new BinaryReader(ms))
2457 {
2458 return Load(cuda, log, br, true, true);
2459 }
2460 }
2461
2466 public override string ToString()
2467 {
2468 string strSize = (HalfSize) ? "HALF " : "FULL ";
2469 return strSize + m_strName + " (" + shape_string + ")";
2470 }
2471
2478 public string ToString(int nMax, bool bDiff = false)
2479 {
2480 double[] rg = Utility.ConvertVec<T>((bDiff) ? update_cpu_diff() : update_cpu_data());
2481 string str = "{";
2482
2483 for (int i = 0; i < rg.Length && i < nMax; i++)
2484 {
2485 str += rg[i].ToString("N4");
2486 str += ",";
2487 }
2488
2489 str = str.TrimEnd(',');
2490 str += "}";
2491
2492 return str;
2493 }
2494
2498 public double min_data
2499 {
2500 get
2501 {
2502 long lPos;
2503 return GetMinData(out lPos);
2504 }
2505 }
2506
2512 public double GetMinData(out long lPos)
2513 {
2514 lPos = -1;
2515 if (count() == 0 || gpu_data == 0)
2516 return 0;
2517
2518 return m_cuda.min(count(), gpu_data, out lPos);
2519 }
2520
2524 public double max_data
2525 {
2526 get
2527 {
2528 long lPos;
2529 return GetMaxData(out lPos);
2530 }
2531 }
2532
2538 public double GetMaxData(out long lPos)
2539 {
2540 lPos = -1;
2541 if (count() == 0 || gpu_data == 0)
2542 return 0;
2543
2544 return m_cuda.max(count(), gpu_data, out lPos);
2545 }
2546
2550 public double min_diff
2551 {
2552 get
2553 {
2554 long lPos;
2555 return GetMinDiff(out lPos);
2556 }
2557 }
2558
2564 public double GetMinDiff(out long lPos)
2565 {
2566 lPos = -1;
2567 if (count() == 0 || gpu_diff == 0)
2568 return 0;
2569
2570 return m_cuda.min(count(), gpu_diff, out lPos);
2571 }
2572
2576 public double max_diff
2577 {
2578 get
2579 {
2580 long lPos;
2581 return GetMaxDiff(out lPos);
2582 }
2583 }
2584
2590 public double GetMaxDiff(out long lPos)
2591 {
2592 lPos = -1;
2593 if (count() == 0 || gpu_diff == 0)
2594 return 0;
2595
2596 return m_cuda.max(count(), gpu_diff, out lPos);
2597 }
2598
2599 private int get_index_up_to(List<int> rgShape, int nMax = 12800)
2600 {
2601 int nIndexUpTo = m_rgShape.Count - 1;
2602 int nNum = m_rgShape[nIndexUpTo];
2603
2604 while (nIndexUpTo > 0 && nNum < nMax)
2605 {
2606 nNum *= m_rgShape[nIndexUpTo-1];
2607 if (nNum < nMax)
2608 nIndexUpTo--;
2609 }
2610
2611 if (nNum > 1 && nIndexUpTo == 0 && m_rgShape.Count > 1)
2612 nIndexUpTo++;
2613
2614 return nIndexUpTo;
2615 }
2616
2624 public Tuple<double, double, double, double> minmax_data(Blob<T> work, bool bDetectNans = false, bool bUseChunks = false)
2625 {
2626 int nCount = count();
2627
2628 if (nCount == 0 || gpu_data == 0)
2629 return new Tuple<double, double, double, double>(0, 0, 0, 0);
2630
2631 if (nCount == 1)
2632 {
2633 double[] rgdf = Utility.ConvertVec<T>(mutable_cpu_data);
2634 return new Tuple<double, double, double, double>(rgdf[0], rgdf[0], double.IsNaN(rgdf[0]) ? 1 : 0, double.IsInfinity(rgdf[0]) ? 1 : 0);
2635 }
2636
2637 work.Reshape(nCount + 64, 1, 1, 1);
2638 work.ReshapeLike(this);
2639
2640 int nIndexUpTo = get_index_up_to(m_rgShape);
2641 if (nIndexUpTo == 0 || nIndexUpTo >= m_rgShape.Count || !bUseChunks)
2642 return m_cuda.minmax(nCount, gpu_data, work.mutable_gpu_data, work.mutable_gpu_diff, bDetectNans);
2643
2644 List<double> rgdfMax = new List<double>();
2645 List<double> rgdfMin = new List<double>();
2646 List<double> rgdfItem3 = new List<double>();
2647 List<double> rgdfItem4 = new List<double>();
2648 List<int> rgShape = new List<int>();
2649 int nNum = 1;
2650
2651 for (int i = 0; i < m_rgShape.Count; i++)
2652 {
2653 if (i < nIndexUpTo)
2654 {
2655 nNum *= m_rgShape[i];
2656 rgShape.Add(1);
2657 }
2658 else
2659 {
2660 rgShape.Add(m_rgShape[i]);
2661 }
2662 }
2663
2664 Blob<T> item = new Blob<T>(m_cuda, m_log, rgShape, false);
2665
2666 for (int i = 0; i < nNum; i++)
2667 {
2668 nCount = item.count();
2669 m_cuda.copy(nCount, gpu_data, item.mutable_gpu_data, i * nCount, 0);
2670 Tuple<double, double, double, double> minmax = m_cuda.minmax(nCount, item.gpu_data, work.mutable_gpu_data, work.mutable_gpu_diff, bDetectNans);
2671 rgdfMin.Add(minmax.Item1);
2672 rgdfMax.Add(minmax.Item2);
2673 rgdfItem3.Add(minmax.Item3);
2674 rgdfItem4.Add(minmax.Item4);
2675 }
2676
2677 item.Dispose();
2678
2679 double dfMin = rgdfMin.Min(p => p);
2680 double dfMax = rgdfMax.Max(p => p);
2681 double dfItem3 = rgdfItem3.Sum(p => p);
2682 double dfItem4 = rgdfItem4.Sum(p => p);
2683
2684 return new Tuple<double, double, double, double>(dfMin, dfMax, dfItem3, dfItem4);
2685 }
2686
2694 public Tuple<double, double, double, double> minmax_diff(Blob<T> work, bool bDetectNans = false, bool bUseChunks = false)
2695 {
2696 int nCount = count();
2697
2698 if (nCount == 0 || gpu_diff == 0)
2699 return new Tuple<double, double, double, double>(0, 0, 0, 0);
2700
2701 if (nCount == 1)
2702 {
2703 double[] rgdf = Utility.ConvertVec<T>(mutable_cpu_diff);
2704 return new Tuple<double, double, double, double>(rgdf[0], rgdf[0], double.IsNaN(rgdf[0]) ? 1 : 0, double.IsInfinity(rgdf[0]) ? 1 : 0);
2705 }
2706
2707 work.Reshape(nCount + 64, 1, 1, 1);
2708 work.ReshapeLike(this);
2709
2710 int nIndexUpTo = get_index_up_to(m_rgShape);
2711 if (nIndexUpTo == 0 || nIndexUpTo >= m_rgShape.Count || !bUseChunks)
2712 return m_cuda.minmax(nCount, gpu_diff, work.mutable_gpu_data, work.mutable_gpu_diff, bDetectNans);
2713
2714 List<double> rgdfMax = new List<double>();
2715 List<double> rgdfMin = new List<double>();
2716 List<double> rgdfItem3 = new List<double>();
2717 List<double> rgdfItem4 = new List<double>();
2718 List<int> rgShape = new List<int>();
2719 int nNum = 1;
2720
2721 for (int i = 0; i < m_rgShape.Count; i++)
2722 {
2723 if (i < nIndexUpTo)
2724 {
2725 nNum *= m_rgShape[i];
2726 rgShape.Add(1);
2727 }
2728 else
2729 {
2730 rgShape.Add(m_rgShape[i]);
2731 }
2732 }
2733
2734 Blob<T> item = new Blob<T>(m_cuda, m_log, rgShape, false);
2735
2736 for (int i = 0; i < nNum; i++)
2737 {
2738 nCount = item.count();
2739 m_cuda.copy(nCount, gpu_diff, item.mutable_gpu_data, i * nCount, 0);
2740 Tuple<double, double, double, double> minmax = m_cuda.minmax(nCount, item.gpu_data, work.mutable_gpu_data, work.mutable_gpu_diff, bDetectNans);
2741 rgdfMin.Add(minmax.Item1);
2742 rgdfMax.Add(minmax.Item2);
2743 rgdfItem3.Add(minmax.Item3);
2744 rgdfItem4.Add(minmax.Item4);
2745 }
2746
2747 item.Dispose();
2748
2749 double dfMin = rgdfMin.Min(p => p);
2750 double dfMax = rgdfMax.Max(p => p);
2751 double dfItem3 = rgdfItem3.Sum(p => p);
2752 double dfItem4 = rgdfItem4.Sum(p => p);
2753
2754 return new Tuple<double, double, double, double>(dfMin, dfMax, dfItem3, dfItem4);
2755 }
2756
2761 {
2762 get { return m_type; }
2763 set { m_type = value; }
2764 }
2765
2769 public object Tag
2770 {
2771 get { return m_tag; }
2772 set { m_tag = value; }
2773 }
2774
2779 public void add_scalar(double dfVal)
2780 {
2781 m_cuda.add_scalar(count(), dfVal, mutable_gpu_data);
2782 }
2783
2784#pragma warning disable 1591
2785
2786 public void rollaxis()
2787 {
2788 long hDataT = m_cuda.AllocMemory(mutable_cpu_data);
2789 m_cuda.matrix_transpose(width * height, channels, hDataT, mutable_gpu_data);
2790 m_cuda.FreeMemory(hDataT);
2791 }
2792
2793 public void save_images(string strPath, Blob<T> blobLabels, double dfScale)
2794 {
2795 if (!Directory.Exists(strPath))
2796 Directory.CreateDirectory(strPath);
2797
2798 T[] rgLabels = blobLabels.update_cpu_data();
2799 T[] rgData = update_cpu_data();
2800
2801 if (dfScale != 1.0)
2802 {
2803 for (int i = 0; i < rgData.Length; i++)
2804 {
2805 double dfVal = Utility.ConvertVal<T>(rgData[i]);
2806
2807 if (dfVal != 0)
2808 {
2809 dfVal /= dfScale;
2810
2811 if (dfVal < 0)
2812 dfVal = 0;
2813
2814 if (dfVal > 255)
2815 dfVal = 255;
2816
2817 rgData[i] = Utility.ConvertVal<T>(dfVal);
2818 }
2819 }
2820 }
2821
2822 strPath = strPath.TrimEnd('\\');
2823
2824 int nCount = channels * height * width;
2825
2826 for (int n = 0; n < num; n++)
2827 {
2828 int nIdx = n * nCount;
2829 Datum d = ImageData.GetImageData<T>(rgData, channels, height, width, false, nIdx, nCount);
2830 Image img = ImageData.GetImage(d);
2831
2832 int nLabel = (int)(float)Convert.ChangeType(rgLabels[n], typeof(float));
2833
2834 string strName = strPath + "\\img_" + n.ToString() + "_label_" + nLabel.ToString() + ".png";
2835 img.Save(strName, System.Drawing.Imaging.ImageFormat.Png);
2836
2837 img.Dispose();
2838 }
2839 }
2840
2841#pragma warning restore 1591
2842
2852 public Blob<T> Resize(List<int> rgShape)
2853 {
2854 m_log.CHECK_EQ(num_axes, rgShape.Count, "When resizing, the new shape must have the same number of axes as the blob to be resized.");
2855 m_log.CHECK_EQ(num_axes, 4, "Resizing only allowed on 4 axis blobs.");
2856 m_log.CHECK_EQ(num, rgShape[0], "Resizing only allowed on the last two axes.");
2857 m_log.CHECK_EQ(channels, rgShape[1], "Resizing only allowed on the last two axes.");
2858
2859 T[] rgData = mutable_cpu_data;
2860 float[] rgDataF = Utility.ConvertVecF<T>(rgData);
2861
2862 Blob<T> newBlob = Clone();
2863 newBlob.Reshape(rgShape);
2864
2865 T[] rgDataNew = newBlob.mutable_cpu_data;
2866 float[] rgDataNewF = Utility.ConvertVecF<T>(rgDataNew);
2867
2868 Bitmap bmp = new Bitmap(width, height);
2869
2870 for (int n = 0; n < num; n++)
2871 {
2872 for (int c = 0; c < channels; c++)
2873 {
2874 float fMin = float.MaxValue;
2875 float fMax = -float.MaxValue;
2876 int nH = height;
2877 int nW = width;
2878 int nSize = nH * nW;
2879
2880 for (int y = 0; y < nH; y++)
2881 {
2882 for (int x = 0; x < nW; x++)
2883 {
2884 int nIdx = n * (channels * nSize) + c * nSize + y * nW + x;
2885 float fVal = rgDataF[nIdx];
2886
2887 if (fVal < fMin)
2888 fMin = fVal;
2889
2890 if (fVal > fMax)
2891 fMax = fVal;
2892 }
2893 }
2894
2895 for (int y = 0; y < nH; y++)
2896 {
2897 for (int x = 0; x < nW; x++)
2898 {
2899 int nIdx = n * (channels * nSize) + c * nSize + y * nW + x;
2900 float fVal = rgDataF[nIdx];
2901
2902 fVal = ((fVal - fMin) / (fMax - fMin)) * 255.0f; // move into range 0,255
2903
2904 bmp.SetPixel(x, y, Color.FromArgb((int)fVal, (int)fVal, (int)fVal));
2905 }
2906 }
2907
2908 Bitmap bmpNew = ImageTools.ResizeImage(bmp, newBlob.width, newBlob.height);
2909
2910 nH = newBlob.height;
2911 nW = newBlob.width;
2912 nSize = nH * nW;
2913
2914 for (int y = 0; y < nH; y++)
2915 {
2916 for (int x = 0; x < nW; x++)
2917 {
2918 int nIdx = n * (channels * nSize) + c * nSize + y * nW + x;
2919
2920 Color clr = bmpNew.GetPixel(x, y);
2921 float fVal = ((clr.R / 255.0f) * (fMax - fMin)) + fMin; // move back to original range.
2922
2923 rgDataNewF[nIdx] = fVal;
2924 }
2925 }
2926
2927 bmpNew.Dispose();
2928 }
2929 }
2930
2931 bmp.Dispose();
2932 newBlob.mutable_cpu_data = Utility.ConvertVec<T>(rgDataNewF);
2933
2934 return newBlob;
2935 }
2936
2942 public void NormalizeData(double? dfMean = null, double? dfStd = null)
2943 {
2944 if (!dfMean.HasValue || !dfStd.HasValue)
2945 {
2946 float[] rgF = Utility.ConvertVecF<T>(update_cpu_data());
2947
2948 dfMean = mean(rgF);
2949 dfStd = std(dfMean.Value, rgF);
2950 }
2951
2952 if (dfMean.Value != 0)
2953 m_cuda.add_scalar(count(), -1 * dfMean.Value, mutable_gpu_data);
2954
2955 if (dfStd.Value != 0 && dfStd.Value != 1.0)
2956 m_cuda.mul_scalar(count(), 1.0 / dfStd.Value, mutable_gpu_data);
2957 }
2958
2965 public double mean(float[] rgDf = null, bool bDiff = false)
2966 {
2967 double dfSum = 0;
2968
2969 if (rgDf == null)
2970 rgDf = Utility.ConvertVecF<T>((bDiff) ? update_cpu_diff() : update_cpu_data());
2971
2972 for (int i = 0; i < rgDf.Length; i++)
2973 {
2974 dfSum += rgDf[i];
2975 }
2976
2977 return dfSum / rgDf.Length;
2978 }
2979
2986 public double sum(float[] rgDf = null, bool bDiff = false)
2987 {
2988 double dfSum = 0;
2989
2990 if (rgDf == null)
2991 rgDf = Utility.ConvertVecF<T>((bDiff) ? update_cpu_diff() : update_cpu_data());
2992
2993 for (int i = 0; i < rgDf.Length; i++)
2994 {
2995 dfSum += rgDf[i];
2996 }
2997
2998 return dfSum;
2999 }
3000
3007 public double std(double? dfMean = null, float[] rgDf = null)
3008 {
3009 double dfSum = 0;
3010
3011 if (rgDf == null)
3012 rgDf = Utility.ConvertVecF<T>(update_cpu_data());
3013
3014 if (!dfMean.HasValue)
3015 dfMean = mean(rgDf);
3016
3017 for (int i = 0; i < rgDf.Length; i++)
3018 {
3019 dfSum += Math.Pow(rgDf[i] - dfMean.Value, 2);
3020 }
3021
3022 return Math.Sqrt(dfSum / rgDf.Length);
3023 }
3024
3035 public Tuple<T, T, T> SetPixel(int nX, int nY, byte R, byte G, byte B, TransformationParameter.COLOR_ORDER order = TransformationParameter.COLOR_ORDER.RGB)
3036 {
3037 int nDim = width * height;
3038 int nIdxR = nY * width + nX;
3039 int nIdxG = nDim + nIdxR;
3040 int nIdxB = nDim + nDim + nIdxR;
3041
3042 if (order == TransformationParameter.COLOR_ORDER.BGR)
3043 {
3044 int nTemp = nIdxB;
3045 nIdxB = nIdxR;
3046 nIdxR = nTemp;
3047 }
3048
3049 T fR = Utility.ConvertVal<T>((double)R);
3050 T fG = Utility.ConvertVal<T>((double)G);
3051 T fB = Utility.ConvertVal<T>((double)B);
3052
3053 T[] rg = m_cuda.SetPixel(mutable_gpu_data, count(), true, 0, new Tuple<int, T>(nIdxR, fR), new Tuple<int, T>(nIdxG, fG), new Tuple<int, T>(nIdxB, fB));
3054
3055 return new Tuple<T, T, T>(rg[0], rg[1], rg[2]);
3056 }
3057
3068 public Tuple<T, T, T> SetPixel(int nX, int nY, Tuple<T, T, T> pixel, bool bReturnOriginal = false, TransformationParameter.COLOR_ORDER order = TransformationParameter.COLOR_ORDER.RGB, int nOffset = 0)
3069 {
3070 int nDim = width * height;
3071 int nIdxR = nY * width + nX;
3072 int nIdxG = nDim + nIdxR;
3073 int nIdxB = nDim + nDim + nIdxR;
3074
3075 if (order == TransformationParameter.COLOR_ORDER.BGR)
3076 {
3077 int nTemp = nIdxB;
3078 nIdxB = nIdxR;
3079 nIdxR = nTemp;
3080 }
3081
3082 T fR = pixel.Item1;
3083 T fG = pixel.Item2;
3084 T fB = pixel.Item3;
3085
3086 if (bReturnOriginal)
3087 {
3088 T[] rg = m_cuda.SetPixel(mutable_gpu_data, count(), true, nOffset, new Tuple<int, T>(nIdxR, fR), new Tuple<int, T>(nIdxG, fG), new Tuple<int, T>(nIdxB, fB));
3089 return new Tuple<T, T, T>(rg[0], rg[1], rg[2]);
3090 }
3091 else
3092 {
3093 m_cuda.SetPixel(mutable_gpu_data, count(), true, nOffset, new Tuple<int, T>(nIdxR, fR), new Tuple<int, T>(nIdxG, fG), new Tuple<int, T>(nIdxB, fB));
3094 return null;
3095 }
3096 }
3097
3105 public void SaveToImage(string strFile, bool bNonZeroExistOnly = true, bool bSaveDiff = false, Dictionary<float, Color> rgSpecialValues = null)
3106 {
3107 Blob<T> blobWork = new Blob<T>(m_cuda, m_log);
3108 float[] rgData;
3109 double dfMin = 1;
3110 double dfMax = 1;
3111 int nWid = width;
3112 int nHt = height;
3113 int nNumY = num;
3114 int nNumX = channels;
3115
3116 try
3117 {
3118 blobWork.ReshapeLike(this);
3119
3120 if (bSaveDiff)
3121 {
3122 rgData = Utility.ConvertVecF<T>(mutable_cpu_diff);
3123
3124 if (!bNonZeroExistOnly)
3125 {
3126 Tuple<double, double, double, double> minmax = minmax_diff(blobWork);
3127 dfMin = minmax.Item1;
3128 dfMax = minmax.Item2;
3129 }
3130 }
3131 else
3132 {
3133 rgData = Utility.ConvertVecF<T>(mutable_cpu_data);
3134
3135 if (!bNonZeroExistOnly)
3136 {
3137 Tuple<double, double, double, double> minmax = minmax_data(blobWork);
3138 dfMin = minmax.Item1;
3139 dfMax = minmax.Item2;
3140 }
3141 }
3142
3143 if (nWid == 1 && nHt == 1)
3144 {
3145 nNumX = 1;
3146 nNumY = 1;
3147 nHt = num;
3148 nWid = channels;
3149 }
3150 else if (nWid == 1)
3151 {
3152 nNumY = num;
3153 nNumX = 1;
3154 nWid = height;
3155 nHt = channels;
3156 }
3157
3158 Bitmap bmp = new Bitmap(nNumX * nWid + (nNumX - 1), nNumY * nHt + (nNumY - 1));
3159 using (Graphics g = Graphics.FromImage(bmp))
3160 {
3161 g.FillRectangle(Brushes.Black, 0, 0, bmp.Width, bmp.Height);
3162 }
3163
3164 LockBitmap bmp1 = new LockBitmap(bmp);
3165 bmp1.LockBits();
3166
3167 int nX = 0;
3168 int nY = 0;
3169 int nX1 = 0;
3170 int nY1 = 0;
3171
3172 for (int y = 0; y < nNumY; y++)
3173 {
3174 for (int x = 0; x < nNumX; x++)
3175 {
3176 for (int h = 0; h < nHt; h++)
3177 {
3178 for (int w = 0; w < nWid; w++)
3179 {
3180 int nIdx = y * nNumX * nHt * nWid + x * nHt * nWid + h * nWid + w;
3181 float fVal = rgData[nIdx];
3182 Color clr = Color.Empty;
3183
3184 if (rgSpecialValues != null && rgSpecialValues.ContainsKey(fVal))
3185 {
3186 clr = rgSpecialValues[fVal];
3187 }
3188 else if (fVal < 0)
3189 {
3190 if (bNonZeroExistOnly)
3191 {
3192 clr = Color.White;
3193 }
3194 else
3195 {
3196 int nClr = (int)(255 * (rgData[nIdx] - dfMin) / (0 - dfMin));
3197 clr = Color.FromArgb(nClr, 0, 0);
3198 }
3199 }
3200 else if (fVal > 0)
3201 {
3202 if (bNonZeroExistOnly)
3203 {
3204 clr = Color.White;
3205 }
3206 else
3207 {
3208 int nClr = (int)(255 * (rgData[nIdx] - 0) / (dfMax - 0));
3209 clr = Color.FromArgb(0, nClr, 0);
3210 }
3211 }
3212
3213 if (!clr.IsEmpty)
3214 bmp1.SetPixel(nX1, nY1, clr);
3215
3216 nX1++;
3217 }
3218
3219 nX1 = nX;
3220 nY1++;
3221 }
3222
3223 nX += nWid + 1;
3224 nX1 = nX;
3225 nY1 = nY;
3226 }
3227
3228 nX = 0;
3229 nY += nHt + 1;
3230 nY1 = nY;
3231 }
3232
3233 bmp1.UnlockBits();
3234 bmp.Save(strFile);
3235 }
3236 finally
3237 {
3238 blobWork.Dispose();
3239 }
3240 }
3241
3247 private void drawImage(Blob<T> b, string strFile)
3248 {
3249 }
3250
3259 public void SaveToNumpy(string strFile, bool bSaveDiff = false)
3260 {
3261 using (FileStream fs = File.Open(strFile, FileMode.Create))
3262 using (BinaryWriter bw = new BinaryWriter(fs))
3263 {
3264 bw.Write((byte)0x93);
3265 bw.Write((byte)0x4E); // N
3266 bw.Write((byte)0x55); // U
3267 bw.Write((byte)0x4D); // M
3268 bw.Write((byte)0x50); // P
3269 bw.Write((byte)0x59); // Y
3270 bw.Write((byte)0x01);
3271 bw.Write((byte)0x00);
3272
3273 string strHeader = "{'descr': '<f4', 'fortran_order': False, 'shape': (";
3274 for (int i = 0; i < shape().Count; i++)
3275 {
3276 strHeader += shape(i).ToString() + ",";
3277 }
3278
3279 strHeader = strHeader.TrimEnd(',');
3280 strHeader += ")";
3281 strHeader += ", }";
3282 strHeader = strHeader.PadRight(117, ' ');
3283 strHeader += "\n";
3284
3285 byte bLen = (byte)strHeader.Length;
3286 bw.Write(bLen);
3287 bw.Write((byte)0x00);
3288
3289 foreach (char ch in strHeader)
3290 {
3291 bw.Write((byte)ch);
3292 }
3293
3294 float[] rgData;
3295 if (bSaveDiff)
3296 rgData = Utility.ConvertVecF<T>(mutable_cpu_diff);
3297 else
3298 rgData = Utility.ConvertVecF<T>(mutable_cpu_data);
3299
3300 for (int i = 0; i < rgData.Length; i++)
3301 {
3302 bw.Write(rgData[i]);
3303 }
3304 }
3305 }
3306
3316 public static void SaveToNumpy(string strFile, float[] rgData, int[] rgShape)
3317 {
3318 using (FileStream fs = File.Open(strFile, FileMode.Create))
3319 using (BinaryWriter bw = new BinaryWriter(fs))
3320 {
3321 bw.Write((byte)0x93);
3322 bw.Write((byte)0x4E); // N
3323 bw.Write((byte)0x55); // U
3324 bw.Write((byte)0x4D); // M
3325 bw.Write((byte)0x50); // P
3326 bw.Write((byte)0x59); // Y
3327 bw.Write((byte)0x01);
3328 bw.Write((byte)0x00);
3329
3330 string strHeader = "{'descr': '<f4', 'fortran_order': False, 'shape': (";
3331 for (int i = 0; i < rgShape.Length; i++)
3332 {
3333 strHeader += rgShape[i].ToString() + ",";
3334 }
3335
3336 strHeader = strHeader.TrimEnd(',');
3337 strHeader += ")";
3338 strHeader += ", }";
3339 strHeader = strHeader.PadRight(117, ' ');
3340 strHeader += "\n";
3341
3342 byte bLen = (byte)strHeader.Length;
3343 bw.Write(bLen);
3344 bw.Write((byte)0x00);
3345
3346 foreach (char ch in strHeader)
3347 {
3348 bw.Write((byte)ch);
3349 }
3350
3351 for (int i = 0; i < rgData.Length; i++)
3352 {
3353 bw.Write(rgData[i]);
3354 }
3355 }
3356 }
3357
3367 public static void SaveToNumpy(string strFile, int[] rgData, int[] rgShape)
3368 {
3369 using (FileStream fs = File.Open(strFile, FileMode.Create))
3370 using (BinaryWriter bw = new BinaryWriter(fs))
3371 {
3372 bw.Write((byte)0x93);
3373 bw.Write((byte)0x4E); // N
3374 bw.Write((byte)0x55); // U
3375 bw.Write((byte)0x4D); // M
3376 bw.Write((byte)0x50); // P
3377 bw.Write((byte)0x59); // Y
3378 bw.Write((byte)0x01);
3379 bw.Write((byte)0x00);
3380
3381 string strHeader = "{'descr': '<i4', 'fortran_order': False, 'shape': (";
3382 for (int i = 0; i < rgShape.Length; i++)
3383 {
3384 strHeader += rgShape[i].ToString() + ",";
3385 }
3386
3387 strHeader = strHeader.TrimEnd(',');
3388 strHeader += ")";
3389 strHeader += ", }";
3390 strHeader = strHeader.PadRight(117, ' ');
3391 strHeader += "\n";
3392
3393 byte bLen = (byte)strHeader.Length;
3394 bw.Write(bLen);
3395 bw.Write((byte)0x00);
3396
3397 foreach (char ch in strHeader)
3398 {
3399 bw.Write((byte)ch);
3400 }
3401
3402 for (int i = 0; i < rgData.Length; i++)
3403 {
3404 bw.Write(rgData[i]);
3405 }
3406 }
3407 }
3408
3418 public static void SaveToNumpy(string strFile, long[] rgData, int[] rgShape)
3419 {
3420 using (FileStream fs = File.Open(strFile, FileMode.Create))
3421 using (BinaryWriter bw = new BinaryWriter(fs))
3422 {
3423 bw.Write((byte)0x93);
3424 bw.Write((byte)0x4E); // N
3425 bw.Write((byte)0x55); // U
3426 bw.Write((byte)0x4D); // M
3427 bw.Write((byte)0x50); // P
3428 bw.Write((byte)0x59); // Y
3429 bw.Write((byte)0x01);
3430 bw.Write((byte)0x00);
3431
3432 string strHeader = "{'descr': '<i8', 'fortran_order': False, 'shape': (";
3433 for (int i = 0; i < rgShape.Length; i++)
3434 {
3435 strHeader += rgShape[i].ToString() + ",";
3436 }
3437
3438 strHeader = strHeader.TrimEnd(',');
3439 strHeader += ")";
3440 strHeader += ", }";
3441 strHeader = strHeader.PadRight(117, ' ');
3442 strHeader += "\n";
3443
3444 byte bLen = (byte)strHeader.Length;
3445 bw.Write(bLen);
3446 bw.Write((byte)0x00);
3447
3448 foreach (char ch in strHeader)
3449 {
3450 bw.Write((byte)ch);
3451 }
3452
3453 for (int i = 0; i < rgData.Length; i++)
3454 {
3455 bw.Write(rgData[i]);
3456 }
3457 }
3458 }
3459
3473 public Tuple<float[], int[]> LoadFromNumpy(string strFile, bool bLoadDiff = false, bool bLoadDataOnly = false, Log log = null, int nMax = int.MaxValue)
3474 {
3475 using (FileStream fs = File.OpenRead(strFile))
3476 using (BinaryReader br = new BinaryReader(fs))
3477 {
3478 byte[] rgMagic = new byte[6];
3479 for (int i = 0; i < rgMagic.Length; i++)
3480 {
3481 rgMagic[i] = br.ReadByte();
3482 }
3483
3484 if (rgMagic[0] != 0x93 || rgMagic[1] != 0x4E || rgMagic[2] != 0x55 || rgMagic[3] != 0x4D || rgMagic[4] != 0x50 || rgMagic[5] != 0x59)
3485 throw new Exception("The file is not a valid Numpy file!");
3486
3487 byte bMajor = br.ReadByte();
3488 byte bMinor = br.ReadByte();
3489
3490 if (bMajor != 1 || bMinor != 0)
3491 throw new Exception("The file is not a valid Numpy file!");
3492
3493 byte bHeaderLen1 = br.ReadByte();
3494 byte bHeaderLen2 = br.ReadByte();
3495 int nHeaderLen = bHeaderLen2 << 8 | bHeaderLen1;
3496
3497 byte[] rgHeader = new byte[nHeaderLen];
3498 for (int i = 0; i < rgHeader.Length; i++)
3499 {
3500 rgHeader[i] = br.ReadByte();
3501 }
3502 string strHeader = Encoding.ASCII.GetString(rgHeader);
3503
3504 bool bFortranOrder;
3505 int[] rgShape;
3506 Type dataType;
3507 int nCount = parseHeader(strHeader, out bFortranOrder, out rgShape, out dataType, nMax);
3508 if (nCount < 0)
3509 throw new Exception("The file size is too large for a flat array.");
3510
3511 if (bFortranOrder)
3512 throw new Exception("Currently the fortran ordering is not supported");
3513
3514 Stopwatch sw = null;
3515 if (log != null)
3516 {
3517 sw = new Stopwatch();
3518 sw.Start();
3519 }
3520
3521 float[] rgData = new float[nCount];
3522 for (int i = 0; i < rgData.Length; i++)
3523 {
3524 if (dataType == typeof(float))
3525 rgData[i] = br.ReadSingle();
3526 else if (dataType == typeof(double))
3527 rgData[i] = (float)br.ReadDouble();
3528 else if (dataType == typeof(int))
3529 rgData[i] = (float)br.ReadInt32();
3530 else if (dataType == typeof(long))
3531 rgData[i] = (float)br.ReadInt64();
3532 else if (dataType == typeof(bool))
3533 rgData[i] = (br.ReadBoolean()) ? 1 : 0;
3534 else
3535 throw new Exception("Unsupported data type!");
3536
3537 if (log != null)
3538 {
3539 if (sw.Elapsed.TotalMilliseconds > 1000)
3540 {
3541 double dfPct = (double)i / (double)rgData.Length;
3542 string strOut = "Loading '" + strFile + "' at " + dfPct.ToString("P5") + "...";
3543 log.WriteLine(strOut, true);
3544 sw.Restart();
3545 }
3546 }
3547 }
3548
3549 if (!bLoadDataOnly)
3550 {
3551 Reshape(rgShape);
3552
3553 if (bLoadDiff)
3554 mutable_cpu_diff = Utility.ConvertVec<T>(rgData);
3555 else
3556 mutable_cpu_data = Utility.ConvertVec<T>(rgData);
3557 }
3558
3559 return new Tuple<float[], int[]>(rgData, rgShape);
3560 }
3561 }
3562
3578 public static Tuple<List<float[]>, int[], List<string>> LoadFromNumpy(string strFile, Log log = null, int nMax = int.MaxValue, int nStartIdx = 0, int nCount = int.MaxValue)
3579 {
3580 using (FileStream fs = File.OpenRead(strFile))
3581 using (BinaryReader br = new BinaryReader(fs))
3582 {
3583 byte[] rgMagic = new byte[6];
3584 for (int i = 0; i < rgMagic.Length; i++)
3585 {
3586 rgMagic[i] = br.ReadByte();
3587 }
3588
3589 if (rgMagic[0] != 0x93 || rgMagic[1] != 0x4E || rgMagic[2] != 0x55 || rgMagic[3] != 0x4D || rgMagic[4] != 0x50 || rgMagic[5] != 0x59)
3590 throw new Exception("The file is not a valid Numpy file!");
3591
3592 byte bMajor = br.ReadByte();
3593 byte bMinor = br.ReadByte();
3594
3595 if (bMajor != 1 || bMinor != 0)
3596 throw new Exception("The file is not a valid Numpy file!");
3597
3598 byte bHeaderLen1 = br.ReadByte();
3599 byte bHeaderLen2 = br.ReadByte();
3600 int nHeaderLen = bHeaderLen2 << 8 | bHeaderLen1;
3601
3602 byte[] rgHeader = new byte[nHeaderLen];
3603 for (int i = 0; i < rgHeader.Length; i++)
3604 {
3605 rgHeader[i] = br.ReadByte();
3606 }
3607 string strHeader = Encoding.ASCII.GetString(rgHeader);
3608
3609 bool bFortranOrder;
3610 int[] rgShape;
3611 Type dataType;
3612 int nDataTypeSize;
3613 Tuple<int,int> count = parseHeaderEx(strHeader, out bFortranOrder, out rgShape, out dataType, out nDataTypeSize, nMax);
3614
3615 if (bFortranOrder)
3616 throw new Exception("Currently the fortran ordering is not supported");
3617
3618 Stopwatch sw = null;
3619 if (log != null)
3620 {
3621 sw = new Stopwatch();
3622 sw.Start();
3623 }
3624
3625 string strVal;
3626 ulong ulIdx = 0;
3627
3628 if (nCount == int.MaxValue)
3629 {
3630 nCount = count.Item1;
3631 }
3632 else
3633 {
3634 if (nStartIdx + nCount > count.Item1)
3635 {
3636 nCount = count.Item1 - nStartIdx;
3637
3638 if (nCount < 0)
3639 nCount = 0;
3640 }
3641
3642 rgShape[0] = nCount;
3643 }
3644
3645 // Skip ahead to start index (if greater than zero).
3646 if (nStartIdx > 0)
3647 {
3648 long nSeekPos = fs.Position;
3649 long nItemSize = 0;
3650 long nItems = 1;
3651
3652 for (int i = 1; i < rgShape.Length; i++)
3653 {
3654 nItems *= rgShape[i];
3655 }
3656
3657 if (nItems > 0)
3658 {
3659 if (dataType == typeof(float))
3660 nItemSize = sizeof(float);
3661 else if (dataType == typeof(double))
3662 nItemSize = sizeof(double);
3663 else if (dataType == typeof(int))
3664 nItemSize = sizeof(int);
3665 else if (dataType == typeof(string))
3666 {
3667 if (nStartIdx > 0)
3668 throw new Exception("String data types do not support starting at an index > 0!");
3669 }
3670 else if (dataType == typeof(long))
3671 nItemSize = sizeof(long);
3672 else if (dataType == typeof(bool))
3673 nItemSize = sizeof(bool);
3674 else
3675 throw new Exception("Unsupported data type!");
3676
3677 nSeekPos += nItemSize * nItems * nStartIdx;
3678
3679 fs.Seek(nSeekPos, SeekOrigin.Begin);
3680 }
3681 }
3682
3683 ulong ulTotal = (ulong)nCount * (ulong)count.Item2;
3684 List<float[]> rgData = new List<float[]>(nCount);
3685 List<string> rgStrData = new List<string>(nCount);
3686 if (ulTotal > 0)
3687 {
3688 for (int i = nStartIdx; i < nStartIdx + nCount && i < count.Item1; i++)
3689 {
3690 float[] rgItem = new float[count.Item2];
3691 for (int j = 0; j < count.Item2; j++)
3692 {
3693 if (dataType == typeof(float))
3694 rgItem[j] = br.ReadSingle();
3695 else if (dataType == typeof(double))
3696 rgItem[j] = (float)br.ReadDouble();
3697 else if (dataType == typeof(int))
3698 rgItem[j] = (float)br.ReadInt32();
3699 else if (dataType == typeof(string))
3700 {
3701 List<byte> bytes = new List<byte>();
3702 byte addByte = 0x00;
3703 for (int c = 0; c < nDataTypeSize * 4; c++)
3704 {
3705 addByte = br.ReadByte();
3706 if (addByte != 0x00)
3707 bytes.Add(addByte);
3708 }
3709 strVal = Encoding.UTF8.GetString(bytes.ToArray());
3710 rgStrData.Add(strVal);
3711 }
3712 else if (dataType == typeof(long))
3713 rgItem[j] = (float)br.ReadInt64();
3714 else if (dataType == typeof(bool))
3715 rgItem[j] = (br.ReadBoolean()) ? 1 : 0;
3716 else
3717 throw new Exception("Unsupported data type!");
3718
3719 if (log != null)
3720 {
3721 if (sw.Elapsed.TotalMilliseconds > 1000)
3722 {
3723 double dfPct = (double)ulIdx / (double)ulTotal;
3724 string strOut = "Loading '" + strFile + "' at " + dfPct.ToString("P5") + "...";
3725 log.WriteLine(strOut, true);
3726 sw.Restart();
3727 }
3728 }
3729 ulIdx++;
3730 }
3731
3732 rgData.Add(rgItem);
3733 }
3734 }
3735
3736 return new Tuple<List<float[]>, int[], List<string>>(rgData, rgShape, rgStrData);
3737 }
3738 }
3739
3740 private int parseHeader(string str, out bool bFortranOrder, out int[] rgShape, out Type dataType, int nMax = int.MaxValue)
3741 {
3742 int nCount = 1;
3743 List<int> rgShape1 = new List<int>();
3744 str = str.Trim('{', '}', ' ', '\n', ',');
3745
3746 dataType = typeof(object);
3747
3748 string strShape = null;
3749 string strTarget = "'shape':";
3750 int nPos = str.IndexOf(strTarget);
3751 if (nPos > 0)
3752 {
3753 strShape = str.Substring(nPos + strTarget.Length);
3754 str = str.Substring(0, nPos);
3755
3756 nPos = strShape.IndexOf(')');
3757 str += strShape.Substring(nPos + 1);
3758 str = str.Trim(',', ' ');
3759
3760 strShape = strShape.Substring(0, nPos);
3761 strShape = strShape.Trim(' ', '(', ')');
3762 string[] rgShapeStr = strShape.Split(',');
3763
3764 for (int i=0; i<rgShapeStr.Length; i++)
3765 {
3766 string strShape1 = rgShapeStr[i];
3767 if (!string.IsNullOrEmpty(strShape1))
3768 {
3769 int nShape = int.Parse(strShape1);
3770
3771 if (i == 0 && nShape > nMax)
3772 nShape = nMax;
3773
3774 rgShape1.Add(nShape);
3775 nCount *= rgShape1[rgShape1.Count - 1];
3776 }
3777 }
3778 }
3779
3780 rgShape = rgShape1.ToArray();
3781 bFortranOrder = false;
3782
3783 string[] rgstr = str.Split(',');
3784 foreach (string str1 in rgstr)
3785 {
3786 string[] rgstrKeyVal = str1.Split(':');
3787 if (rgstrKeyVal.Length != 2)
3788 throw new Exception("Invalid header key value, '" + str1 + "'!");
3789
3790 string strKey = rgstrKeyVal[0].Trim('\'', ' ');
3791 string strVal = rgstrKeyVal[1].Trim('\'', ' ');
3792
3793 switch (strKey)
3794 {
3795 case "descr":
3796 if (strVal == "<f4")
3797 dataType = typeof(float);
3798 else if (strVal == "<f8")
3799 dataType = typeof(double);
3800 else if (strVal == "<i4")
3801 dataType = typeof(int);
3802 else if (strVal == "<i8")
3803 dataType = typeof(long);
3804 else if (strVal == "|b1")
3805 dataType = typeof(bool);
3806 else
3807 throw new Exception("Unsupported data type '" + strVal + "', currenly only support '<f4'");
3808 break;
3809
3810 case "fortran_order":
3811 bFortranOrder = bool.Parse(strVal);
3812 break;
3813 }
3814 }
3815
3816 return nCount;
3817 }
3818
3819 private static Tuple<int, int> parseHeaderEx(string str, out bool bFortranOrder, out int[] rgShape, out Type dataType, out int nDataTypeSize, int nMax = int.MaxValue)
3820 {
3821 int nNum = 1;
3822 int nCount = 1;
3823 List<int> rgShape1 = new List<int>();
3824 str = str.Trim('{', '}', ' ', '\n', ',');
3825
3826 dataType = typeof(object);
3827 nDataTypeSize = 1;
3828
3829 string strShape = null;
3830 string strTarget = "'shape':";
3831 int nPos = str.IndexOf(strTarget);
3832 if (nPos > 0)
3833 {
3834 strShape = str.Substring(nPos + strTarget.Length);
3835 str = str.Substring(0, nPos);
3836
3837 nPos = strShape.IndexOf(')');
3838 str += strShape.Substring(nPos + 1);
3839 str = str.Trim(',', ' ');
3840
3841 strShape = strShape.Substring(0, nPos);
3842 strShape = strShape.Trim(' ', '(', ')');
3843 string[] rgShapeStr = strShape.Split(',');
3844
3845 for (int i=0; i<rgShapeStr.Count(); i++)
3846 {
3847 string strShape1 = rgShapeStr[i];
3848 if (!string.IsNullOrEmpty(strShape1))
3849 {
3850 int nShape = int.Parse(strShape1);
3851
3852 if (i == 0 && nShape > nMax)
3853 nShape = nMax;
3854
3855 rgShape1.Add(nShape);
3856
3857 if (i == 0)
3858 nNum = rgShape1[rgShape1.Count - 1];
3859 else
3860 nCount *= rgShape1[rgShape1.Count - 1];
3861 }
3862 }
3863 }
3864
3865 rgShape = rgShape1.ToArray();
3866 bFortranOrder = false;
3867
3868 string[] rgstr = str.Split(',');
3869 foreach (string str1 in rgstr)
3870 {
3871 string[] rgstrKeyVal = str1.Split(':');
3872 if (rgstrKeyVal.Length != 2)
3873 throw new Exception("Invalid header key value, '" + str1 + "'!");
3874
3875 string strKey = rgstrKeyVal[0].Trim('\'', ' ');
3876 string strVal = rgstrKeyVal[1].Trim('\'', ' ');
3877
3878 switch (strKey)
3879 {
3880 case "descr":
3881 if (strVal == "<f4")
3882 dataType = typeof(float);
3883 else if (strVal == "<f8")
3884 dataType = typeof(double);
3885 else if (strVal == "<i4")
3886 dataType = typeof(int);
3887 else if (strVal == "<i8")
3888 dataType = typeof(long);
3889 else if (strVal == "|b1")
3890 dataType = typeof(bool);
3891 else if (strVal.StartsWith("<U"))
3892 {
3893 strVal = strVal.Substring(2);
3894 nDataTypeSize = int.Parse(strVal);
3895 dataType = typeof(string);
3896 }
3897 else
3898 throw new Exception("Unsupported data type '" + strVal + "', currenly only support '<f4'");
3899 break;
3900
3901 case "fortran_order":
3902 bFortranOrder = bool.Parse(strVal);
3903 break;
3904 }
3905 }
3906
3907 return new Tuple<int, int>(nNum, nCount);
3908 }
3909
3922 public void MatMul(Blob<T> blobA, Blob<T> blobB, bool bReshape = false, bool bTransA = false, bool bTransB = false, double dfScale = 1.0, bool bADiff = false, bool bBDiff = false, bool bCDiff = false)
3923 {
3924 m_log.CHECK_EQ(blobA.num_axes, 4, "The blobA must have 4 axes!");
3925 m_log.CHECK_EQ(blobB.num_axes, 4, "The blobB must have 4 axes!");
3926
3927 if (bADiff && blobA.gpu_diff == 0)
3928 m_log.FAIL("Blob A does not have a diff value!");
3929 if (bBDiff && blobB.gpu_diff == 0)
3930 m_log.FAIL("Blob B does not have a diff value!");
3931
3932 for (int i = 0; i < blobA.num_axes - 2; i++)
3933 {
3934 m_log.CHECK_EQ(blobA.shape(i), blobB.shape(i), "Blob A and B must have the same shape at axis '" + i.ToString() + "'!");
3935 }
3936
3937 if (bCDiff && gpu_diff == 0)
3938 m_log.FAIL("This blob does not have a diff value!");
3939
3940 int nAxis = 2;
3941 uint nOuterCount = (uint)blobA.count(0, nAxis);
3942 int m = blobA.shape(2);
3943 int n = blobB.shape(3);
3944 int k = blobA.shape(3);
3945
3946 // Reshape the resulting blob to shape (B,C,M,N)
3947 List<int> rgShape = Utility.Clone<int>(blobA.shape());
3948 rgShape[rgShape.Count - 1] = n;
3949 rgShape[rgShape.Count - 2] = m;
3950
3951 if (bReshape)
3952 Reshape(rgShape);
3953 else
3954 m_log.CHECK(CompareShape(rgShape), "This (resulting) blob does not have the correct shape! Expected shape = " + Utility.ToString<int>(rgShape));
3955
3956 long hA = (bADiff) ? blobA.gpu_diff : blobA.gpu_data;
3957 long hB = (bBDiff) ? blobB.gpu_diff : blobB.gpu_data;
3958 long hC = (bCDiff) ? mutable_gpu_diff : mutable_gpu_data;
3959
3960 m_cuda.matmul(nOuterCount, m, n, k, hA, hB, hC, dfScale, bTransA, bTransB);
3961 }
3962
3974 public void MatMulGrad(Blob<T> blobA, Blob<T> blobB, Blob<T> blobWork, double dfScale = 1.0)
3975 {
3976 if (dfScale != 1.0)
3977 scale_diff(dfScale);
3978 blobWork.CopyFromAndTransposeHeightWidth(blobB, false);
3979 blobA.MatMul(this, blobWork, false, false, false, 1, true, false, true);
3980 blobWork.CopyFromAndTransposeHeightWidth(blobA, false);
3981 blobB.MatMul(blobWork, this, false, false, false, 1, false, true, true);
3982 }
3983
3992 public void Percentile(Blob<T> blobY, double dfPercentile)
3993 {
3994 List<int> rgShape = Utility.Clone<int>(shape());
3995 rgShape[0] = 1;
3996 blobY.Reshape(rgShape);
3997
3998 m_cuda.channel_percentile(m_nCount, num, channels, count(2), gpu_data, blobY.mutable_gpu_data, dfPercentile);
3999 }
4000 }
4001}
The Datum class is a simple wrapper to the SimpleDatum class to ensure compatibility with the origina...
Definition: Datum.cs:12
The ImageData class is a helper class used to convert between Datum, other raw data,...
Definition: ImageData.cs:14
static Datum GetImageData(Bitmap bmp, SimpleDatum sd, bool? bIsDataRealOverride=null, int[] rgFocusMap=null)
The GetImageData function converts a Bitmap into a Datum.
Definition: ImageData.cs:23
static Bitmap GetImage(SimpleDatum d, ColorMapper clrMap=null, List< int > rgClrOrder=null)
Converts a SimplDatum (or Datum) into an image, optionally using a ColorMapper.
Definition: ImageData.cs:506
The ImageTools class is a helper class used to manipulate image data.
Definition: ImageTools.cs:16
static Bitmap ResizeImage(Image image, int width, int height)
Resize the image to the specified width and height.
Definition: ImageTools.cs:39
The LockBitmap class provides very efficient SetPixel and GetPixel functionality of a bitmap by using...
Definition: LockBitmap.cs:21
void SetPixel(int x, int y, Color color)
Set the color of the specified pixel
Definition: LockBitmap.cs:164
void UnlockBits()
Unlock bitmap data, releasing its underlying data.
Definition: LockBitmap.cs:99
void LockBits()
Lock bitmap data to access its underlying raw data.
Definition: LockBitmap.cs:55
The Log class provides general output in text form.
Definition: Log.cs:13
void CHECK(bool b, string str)
Test a flag for true.
Definition: Log.cs:227
void WriteLine(string str, bool bOverrideEnabled=false, bool bHeader=false, bool bError=false, bool bDisable=false)
Write a line of output.
Definition: Log.cs:80
void FAIL(string str)
Causes a failure which throws an exception with the desciptive text.
Definition: Log.cs:394
void CHECK_EQ(double df1, double df2, string str)
Test whether one number is equal to another.
Definition: Log.cs:239
void CHECK_LE(double df1, double df2, string str)
Test whether one number is less than or equal to another.
Definition: Log.cs:263
void CHECK_GE(double df1, double df2, string str)
Test whether one number is greater than or equal to another.
Definition: Log.cs:287
void CHECK_LT(double df1, double df2, string str)
Test whether one number is less than another.
Definition: Log.cs:275
The SimpleDatum class holds a data input within host memory.
Definition: SimpleDatum.cs:161
int Channels
Return the number of channels of the data.
int Width
Return the width of the data.
int Index
Returns the index of the SimpleDatum.
int Height
Return the height of the data.
The Utility class provides general utility funtions.
Definition: Utility.cs:35
static int CanonicalAxisIndex(int nIdx, int nNumAxes)
Returns the 'canonical' version of a (usually) user-specified axis, allowing for negative indexing (e...
Definition: Utility.cs:50
static int Count(List< int > rgShape, int nStartIdx=0, int nEndIdx=-1)
Return the count of items given the shape.
Definition: Utility.cs:83
static double[] ConvertVec(float[] rgf)
Convert an array of float to an array of generics.
Definition: Utility.cs:550
The Blob is the main holder of data that moves through the Layers of the Net.
Definition: Blob.cs:25
Blob< T > MathDiv(T fScale)
Clones the input Blob and divides a scalar from all of the clones data items.
Definition: Blob.cs:2264
void Percentile(Blob< T > blobY, double dfPercentile)
Calculates the percentile and places the result in blobY.
Definition: Blob.cs:3992
int channels
DEPRECIATED; legacy shape accessor channels: use shape(1) instead.
Definition: Blob.cs:800
Blob(CudaDnn< T > cuda, Log log, List< int > rgShape, bool bIncludeDiff=true, bool bUseHalfSize=false)
The Blob constructor.
Definition: Blob.cs:115
double sum(float[] rgDf=null, bool bDiff=false)
Calculate the sum of the blob data.
Definition: Blob.cs:2986
void SetData(T[] rgData, int nCount=-1, bool bSetCount=true)
Sets a number of items within the Blob's data.
Definition: Blob.cs:1922
void ShareData(Blob< T > b)
Set the data to point to the data of the other blob – useful in Layers which simply perform a copy in...
Definition: Blob.cs:1813
double min_data
Returns the minimum value in the data of the Blob.
Definition: Blob.cs:2499
double max_data
Returns the maximum value in the data of the Blob.
Definition: Blob.cs:2525
int LegacyShape(int nIdx)
Returns the legacy shape at a given axis.
Definition: Blob.cs:825
void MatMul(Blob< T > blobA, Blob< T > blobB, bool bReshape=false, bool bTransA=false, bool bTransB=false, double dfScale=1.0, bool bADiff=false, bool bBDiff=false, bool bCDiff=false)
MatMul blobA with blobB and place the result in this blob (e.g. this = matmul(A, B))....
Definition: Blob.cs:3922
int height
DEPRECIATED; legacy shape accessor height: use shape(2) instead.
Definition: Blob.cs:808
Blob(CudaDnn< T > cuda, Log log, Blob< T > b, bool bUseHalfSize=false)
The Blob constructor.
Definition: Blob.cs:146
int count(int nStartIdx)
Compute the volume of a slice spanning from a particular first axis to the final axis.
Definition: Blob.cs:768
void MatMulGrad(Blob< T > blobA, Blob< T > blobB, Blob< T > blobWork, double dfScale=1.0)
Calculates and propagates the gradient for blobA and BlobB given the input gradient in this blob's di...
Definition: Blob.cs:3974
int count(int nStartIdx, int nEndIdx)
Compute the volume of a slice; i.e., the product of dimensions among a range of axes.
Definition: Blob.cs:751
Blob(CudaDnn< T > cuda, Log log, bool bIncludeDiff=true, bool bUseHalfSize=false)
The Blob constructor.
Definition: Blob.cs:64
int num_axes
Returns the number of axes in the Blob.
Definition: Blob.cs:705
Tuple< double, double, double, double > minmax_data(Blob< T > work, bool bDetectNans=false, bool bUseChunks=false)
Returns the minimum and maximum values in the data of the Blob.
Definition: Blob.cs:2624
double? GetParameter(string strName)
Get a blob parameter.
Definition: Blob.cs:220
long mutable_gpu_diff
Returns the diff GPU handle used by the CudaDnn connection.
Definition: Blob.cs:1555
void SaveToImage(string strFile, bool bNonZeroExistOnly=true, bool bSaveDiff=false, Dictionary< float, Color > rgSpecialValues=null)
Save the Blob to an image where values less than 0 are colored red, and values greater than 0 are col...
Definition: Blob.cs:3105
void scale_diff(T fScaleFactor)
Scale the blob diff by a constant factor.
Definition: Blob.cs:1791
Tuple< T, T, T > SetPixel(int nX, int nY, Tuple< T, T, T > pixel, bool bReturnOriginal=false, TransformationParameter.COLOR_ORDER order=TransformationParameter.COLOR_ORDER.RGB, int nOffset=0)
Sets a pixel to the values within a three item tuple where the first item is assigned RED,...
Definition: Blob.cs:3068
T[] mutable_cpu_diff
Get diff from the GPU and bring it over to the host, or Set diff from the Host and send it over to th...
Definition: Blob.cs:1511
T GetDiff(int nIdx)
Returns the diff at a given flat index within the Blob.
Definition: Blob.cs:1907
bool CompareShape(int[] rgShape, bool bCompareCpuDataLen=false)
Compares the shape of this blob to another shape.
Definition: Blob.cs:2148
T data_at(int n, int c, int h, int w)
Returns the data at a given location in the Blob.
Definition: Blob.cs:1394
T sumsq_diff()
Calcualte the sum of squares (L2 norm squared) of the diff.
Definition: Blob.cs:1742
long mutable_gpu_data
Returns the data GPU handle used by the CudaDnn connection.
Definition: Blob.cs:1487
void SetDiff(double dfVal, int nStartIdx, int nCount)
Set a diff range with a given value.
Definition: Blob.cs:1998
void Share(Blob< T > b)
Share another Blob with this one, by setting the data and diff to the same data and diff of the other...
Definition: Blob.cs:1850
Blob(CudaDnn< T > cuda, Log log, int nNum, int nChannels, int nHeight, int nWidth, bool bIncludeDiff=true, bool bUseHalfSize=false)
DEPRECIATED; use
Definition: Blob.cs:98
object Tag
Returns a user defined object associated with the Blob.
Definition: Blob.cs:2770
void Unsqueeze(int nNumAxes)
Unsqueeze the shape by adding shape=1 on each axis until the 'nNumAxes' is reached.
Definition: Blob.cs:201
void CopyFromAndTransposeHeightWidth(Blob< T > blobSrc, bool bCopyDiff=false, bool bUseCuda=true)
Copy from a source Blob and transpose the height and width of the copy.
Definition: Blob.cs:1002
static Blob< T > Load(CudaDnn< T > cuda, Log log, BinaryReader br, bool bData, bool bDiff)
Lods a new Blob from a binary reader.
Definition: Blob.cs:2377
int num_true_axes
Returns the number of true axes, ignoring the trailing ones.
Definition: Blob.cs:716
bool HalfSize
Returns whether or not this blob is using half sizes.
Definition: Blob.cs:369
void Update()
The 'update' method is used for parameter blobs in a Net.
Definition: Blob.cs:1575
string shape_string
Returns a string describing the Blob's shape.
Definition: Blob.cs:657
static Blob< T > FromByteArray(CudaDnn< T > cuda, Log log, byte[] rg)
A new Blob is created from the byte array, previously saved with ToByteArray.
Definition: Blob.cs:2453
int offset(List< int > rgIdx)
Returns the flat offset given the array of axes values.
Definition: Blob.cs:873
void SetCPUData(T[] rg)
Sets just the CPU data to the data specified.
Definition: Blob.cs:2052
void Reshape(BlobShape shape, bool? bUseHalfSize=null)
Change the dimensions of the blob, allocating new memory if necessary.
Definition: Blob.cs:637
void CopyParameters(Blob< T > b)
Copy the parameters from another blob.
Definition: Blob.cs:245
T[] mutable_cpu_data
Get data from the GPU and bring it over to the host, or Set data from the Host and send it over to th...
Definition: Blob.cs:1461
static void SaveToNumpy(string strFile, long[] rgData, int[] rgShape)
Save a blob with data to a Numpy .npy file.
Definition: Blob.cs:3418
T asum_diff()
Compute the sum of absolute values (L1 norm) of the diff.
Definition: Blob.cs:1718
static Tuple< List< float[]>, int[], List< string > > LoadFromNumpy(string strFile, Log log=null, int nMax=int.MaxValue, int nStartIdx=0, int nCount=int.MaxValue)
Load the long, int, bool, float, or double data from a very large Numpy array .npy file,...
Definition: Blob.cs:3578
static T One
Returns One (1) in type T.
Definition: Blob.cs:268
Blob< T > Clone()
Copies the Blob, including its data and diff.
Definition: Blob.cs:2202
void ConvertToBase(long hWorkMem, ulong lWorkSize, bool bData, bool bDiff)
Converts this blob from the half type to the base type.
Definition: Blob.cs:339
bool DiffExists
Returns whether or not the Diff portion exists.
Definition: Blob.cs:676
SyncedMemory< T > diff
Returns the SyncedMemory that stores the diff.
Definition: Blob.cs:1444
void ConvertToHalf(long hWorkMem, ulong lWorkSize, bool bData, bool bDiff)
Converts this blob from its base type to the half type.
Definition: Blob.cs:306
void Reshape(List< int > rgShape, bool? bUseHalfSize=null)
Change the dimensions of the blob, allocating new memory if necessary.
Definition: Blob.cs:562
Blob(CudaDnn< T > cuda, Log log, SimpleDatum d, bool bCopyData=false, bool bIncludeDiff=true, bool bUseHalfSize=false)
The Blob constructor.
Definition: Blob.cs:163
int CanonicalAxisIndex(int nIdx)
Returns the 'canonical' version of a (usually) user-specified axis, allowing for negative indexing (e...
Definition: Blob.cs:780
Blob(CudaDnn< T > cuda, Log log, int[] rgShape, bool bIncludeDiff=true, bool bUseHalfSize=false)
The Blob constructor.
Definition: Blob.cs:131
T[] cpu_data
Returns the last host data retrieved from the GPU.
Definition: Blob.cs:1452
void SaveToNumpy(string strFile, bool bSaveDiff=false)
Save a blob with data to a Numpy .npy file.
Definition: Blob.cs:3259
void Reshape(int nNum, int nChannels, int nHeight, int nWidth, bool? bUseHalfSize=null)
DEPRECIATED; use
Definition: Blob.cs:442
BLOB_TYPE type
Returns the BLOB_TYPE of the Blob.
Definition: Blob.cs:2761
double GetMinData(out long lPos)
Returns the minimum data and the position where the minimum is located in the data.
Definition: Blob.cs:2512
double std(double? dfMean=null, float[] rgDf=null)
Calculate the standard deviation of the blob data.
Definition: Blob.cs:3007
Blob< T > MathSub(Blob< T > blobA)
Clones the input Blob and subtracts the data from this blob from it.
Definition: Blob.cs:2247
double GetMaxDiff(out long lPos)
Returns the maximum diff and the position where the maximum is located in the diff.
Definition: Blob.cs:2590
double min_diff
Returns the minimum value in the diff of the Blob.
Definition: Blob.cs:2551
Datum ToDatum()
Returns a new Datum that contains the shape and data of the Blob.
Definition: Blob.cs:2166
Tuple< double, double, double, double > minmax_diff(Blob< T > work, bool bDetectNans=false, bool bUseChunks=false)
Returns the minimum and maximum values in the diff of the Blob.
Definition: Blob.cs:2694
long CopyFrom(Blob< T > src, bool bCopyDiff=false, bool bReshape=false, long hDstHostBuffer=0, bool bIgnoreShape=false)
Copy from a source Blob.
Definition: Blob.cs:928
double mean(float[] rgDf=null, bool bDiff=false)
Calculate the mean of the blob data.
Definition: Blob.cs:2965
static void SaveToNumpy(string strFile, int[] rgData, int[] rgShape)
Save a blob with data to a Numpy .npy file.
Definition: Blob.cs:3367
bool CompareShape(List< int > rgShape, bool bCompareCpuDataLen=false)
Compares the shape of this blob to another shape.
Definition: Blob.cs:2108
void Dispose()
Releases all resources used by the Blob (including both GPU and Host).
Definition: Blob.cs:429
bool reshape_when_sharing
When true, this Blob is reshaped to the source when sharing the source data (default = false).
Definition: Blob.cs:1803
byte[] ToByteArray()
Saves this Blob to a byte array.
Definition: Blob.cs:2436
int shape(int nIdx)
Returns the dimension of the nIdx'th axis (or the negative nIdx'th axis from teh end,...
Definition: Blob.cs:696
Blob< T > MathAdd(Blob< T > blobA, T fScale)
Clones the input Blob, scales the clone and then adds the data from this Blob to it.
Definition: Blob.cs:2227
bool Compare(Blob< T > other, Blob< T > work, bool bDiff=false, double dfTol=1e-8, bool bZeroCheck=true, bool bFullCompare=false, bool bDetectNans=true, bool bForceOtherData=false)
Compare the data (or diff) of one blob to another and return true if all items fall within the specif...
Definition: Blob.cs:1093
void CopyFrom(Blob< T > src, int nSrcOffset, int nDstOffset, int nCount, bool bCopyData, bool bCopyDiff)
Copy from a source Blob.
Definition: Blob.cs:903
void scale_to_range(double dfMin, double dfMax)
Scale the data in the blob to the range [dfMin,dfMax].
Definition: Blob.cs:1773
bool ShapeEquals(BlobProto bp)
Compares the shape of this blob to the shape within a BlobProto.
Definition: Blob.cs:2079
T[] update_cpu_diff()
Update the CPU diff by transferring the GPU diff over to the Host.
Definition: Blob.cs:1529
void scale_data(double df)
Scale the data by a scaling factor.
Definition: Blob.cs:1754
int width
DEPRECIATED; legacy shape accessor width: use shape(3) instead.
Definition: Blob.cs:816
void FromProto(BlobProto bp, bool bReshape=true)
Create a new Blob from a given BlobProto.
Definition: Blob.cs:1589
T diff_at(List< int > rgIdx)
Returns the diff at a given location in the Blob.
Definition: Blob.cs:1427
double GetMinDiff(out long lPos)
Returns the minimum diff and the position where the minimum is located in the diff.
Definition: Blob.cs:2564
long gpu_shape
Returns the shape GPU handle used by the CudaDnn connection. The shape data contains the shape inform...
Definition: Blob.cs:1565
void add_scalar(double dfVal)
Adds a scalar value to the Blob.
Definition: Blob.cs:2779
void SetParameter(string strName, double dfVal)
Set a blob parameter.
Definition: Blob.cs:233
Tuple< T, T, T > SetPixel(int nX, int nY, byte R, byte G, byte B, TransformationParameter.COLOR_ORDER order=TransformationParameter.COLOR_ORDER.RGB)
Set the values of a 3 channel image embedded within the blob in the order RGB or BGR where the full h...
Definition: Blob.cs:3035
BlobProto ToProto(bool bWriteDiff=false)
Writes the Blob to a new BlobProto.
Definition: Blob.cs:1663
Blob(Blob< T > blob, long lCount, long lOffset)
The Blob constructor used to copy another blob by creating memory pointers to its data thus sharing t...
Definition: Blob.cs:188
void Reshape(int[] rgShape, bool? bUseHalfSize=null)
Change the dimensions of the blob, allocating new memory if necessary.
Definition: Blob.cs:583
Tuple< float[], int[]> LoadFromNumpy(string strFile, bool bLoadDiff=false, bool bLoadDataOnly=false, Log log=null, int nMax=int.MaxValue)
Load a blob with data from a Numpy array .npy file.
Definition: Blob.cs:3473
void AsyncGpuPush(long hStream)
Asynchronously pushes the CPU data, previously set with SetCPUData, to the GPU.
Definition: Blob.cs:2062
ulong GetConversionWorkSize(bool bUseHalfSize)
Returns the amount of memory (in bytes) required to convert from base to half and back.
Definition: Blob.cs:293
bool freeze_learning
Specifies whether or not the diff is applied to the data during Update. When freeze learning = true,...
Definition: Blob.cs:377
double max_diff
Returns the maximum value in the diff of the Blob.
Definition: Blob.cs:2577
List< int > shape()
Returns an array where each element contains the shape of an axis of the Blob.
Definition: Blob.cs:684
static T Zero
Returns Zero (0) in type T.
Definition: Blob.cs:260
T GetData(int nIdx)
Returns the data at a given flat index within the Blob.
Definition: Blob.cs:1893
SyncedMemory< T > data
Returns the SyncedMemory that stores the data.
Definition: Blob.cs:1436
T sumsq_data()
Calcualte the sum of squares (L2 norm squared) of the data.
Definition: Blob.cs:1730
bool CompareEx(Blob< T > other, Blob< T > work, out double dfMin, out double dfMax, bool bDiff=false, double dfTol=1e-8, bool bZeroCheck=true, bool bFullCompare=false, bool bDetectNans=true, bool bForceOtherData=false)
Compare the data (or diff) of one blob to another and return true if all items fall within the specif...
Definition: Blob.cs:1114
static void SaveToNumpy(string strFile, float[] rgData, int[] rgShape)
Save a blob with data to a Numpy .npy file.
Definition: Blob.cs:3316
T[] update_cpu_data()
Update the CPU data by transferring the GPU data over to the Host.
Definition: Blob.cs:1470
override string ToString()
Returns a string representation of the Blob.
Definition: Blob.cs:2466
void Save(BinaryWriter bw, bool bData, bool bDiff, bool bIncludeName=true)
Saves this Blob to a binary stream.
Definition: Blob.cs:2298
T asum_data()
Compute the sum of absolute values (L1 norm) of the data.
Definition: Blob.cs:1706
const int MAX_BLOB_AXES
Defines the maximum number of Axes supported by the Blob.
Definition: Blob.cs:55
void NormalizeData(double? dfMean=null, double? dfStd=null)
Normalize the blob data by subtracting the mean and dividing by the standard deviation.
Definition: Blob.cs:2942
void scale_data(T fScaleFactor)
Scale the blob data by a constant factor.
Definition: Blob.cs:1782
static Blob< T > LoadBinary(CudaDnn< T > cuda, Log log, string strFile, bool bData, bool bDiff)
Loads a blob from a binary file (previously saved with SaveBinary).
Definition: Blob.cs:2359
int count()
Returns the total number of items in the Blob.
Definition: Blob.cs:739
void ShareDiff(Blob< T > b)
Set the diff to point to the diff of the other blob – useful in Layers which simply perform a copy in...
Definition: Blob.cs:1832
void SetData(SimpleDatum d, bool bReshape, bool bCopyData=true)
Sets the Blob values to the data contained within a SimpleDatum.
Definition: Blob.cs:2029
void CopyFromAndPad(Blob< T > src, double dfPad=0, bool bCopyDiff=false)
Copy the source data to this Blob, and if this blob is larger than the source, pad this blob with 'df...
Definition: Blob.cs:973
void ReshapeLike(Blob< T > b, bool? bUseHalfSize=null)
Reshape this Blob to have the same shape as another Blob.
Definition: Blob.cs:648
bool Compare(CudaDnn< double > cuda, Blob< T > other, Blob< double > work, bool bDiff=false, double dfTol=1e-8)
Compare the data (or diff) of one blob to another and return true if all items fall within the specif...
Definition: Blob.cs:1220
T diff_at(int n, int c, int h, int w)
Returns the diff at a given location in the Blob.
Definition: Blob.cs:1407
string Name
Get/set the name of the Blob.
Definition: Blob.cs:2184
int offset(int n, int c=0, int h=0, int w=0)
Returns the flat offset given the number, channel, height and width.
Definition: Blob.cs:850
CudaDnn< T > Cuda
Returns the CudaDnn object that manages the Blob's memory."/>
Definition: Blob.cs:386
long gpu_diff
Returns the diff GPU handle used by the CudaDnn connection.
Definition: Blob.cs:1541
virtual void Dispose(bool bDisposing)
Releases all resources used by the Blob (including both GPU and Host).
Definition: Blob.cs:402
T data_at(List< int > rgIdx)
Returns the data at a given location in the Blob.
Definition: Blob.cs:1417
void SetData(double dfVal, int nStartIdx, int nCount)
Set a data range with a given value.
Definition: Blob.cs:1961
string ToSizeString()
Returns a string describing the 4D shape of the Blob.
Definition: Blob.cs:2157
void SaveBinary(string strFile, bool bData, bool bDiff, bool bIncludeName=true)
Saves the blob to a binary file.
Definition: Blob.cs:2282
string ToString(int nMax, bool bDiff=false)
Get the string representation containing up to the first 'nMax' items.
Definition: Blob.cs:2478
void SetDiff(T[] rgDiff, int nCount=-1, bool bSetCount=true)
Sets a number of items within the Blob's diff.
Definition: Blob.cs:2018
Blob(CudaDnn< T > cuda, Log log, BlobProto bp, bool bUseHalfSize=false)
The Blob constructor.
Definition: Blob.cs:176
void scale_diff(double df)
Scale the diff by a scaling factor.
Definition: Blob.cs:1763
bool Padded
Get/set the padding state of the blob.
Definition: Blob.cs:284
void SetDiff(double dfVal, int nIdx=-1)
Either sets all of the diff items in the Blob to a given value, or alternatively only sets a single i...
Definition: Blob.cs:1981
void CopyFrom(Blob< T > blobSrc, int nChannelFrom, int nChannelTo, bool bCopyDiff=false)
Copy all data along a given channel from the source.
Definition: Blob.cs:1054
int num
DEPRECIATED; legacy shape accessor num: use shape(0) instead.
Definition: Blob.cs:792
T[] cpu_diff
Returns the last host diff retrieved from the GPU.
Definition: Blob.cs:1496
static T MinusOne
Returns MinusOne (-1) in type T.
Definition: Blob.cs:276
void SetData(T fVal, int nIdx=-1)
Either sets all of the data items in the Blob to a given value, or alternatively only sets a single i...
Definition: Blob.cs:1933
bool ValidateData(Blob< T > work, bool bDiff=false)
Validate the data or diff looking for NAN or Inf.
Definition: Blob.cs:1197
bool snapshot_requested
Get/set the snapshot request.
Definition: Blob.cs:1883
Blob< T > Resize(List< int > rgShape)
The Resize method resizes the 3rd and 4th axes of the blob.
Definition: Blob.cs:2852
long gpu_data
Returns the data GPU handle used by the CudaDnn connection.
Definition: Blob.cs:1479
void SetData(double dfVal, int nIdx=-1)
Either sets all of the data items in the Blob to a given value, or alternatively only sets a single i...
Definition: Blob.cs:1947
double GetMaxData(out long lPos)
Returns the maximum data and the position where the maximum is located in the data.
Definition: Blob.cs:2538
The CudaDnn object is the main interface to the Low-Level Cuda C++ DLL.
Definition: CudaDnn.cs:969
void matmul(uint nOuterCount, int m, int n, int k, long hA, long hB, long hC, double dfScale=1.0, bool bTransA=false, bool bTransB=false)
Perform matmul operation hC = matmul(hA, hB), where hA, hB and hC are all in row-major format.
Definition: CudaDnn.cs:6695
void copy(int nCount, long hSrc, long hDst, int nSrcOffset=0, int nDstOffset=0, long hStream=-1, bool? bSrcHalfSizeOverride=null, bool? bDstHalfSizeOverride=null)
Copy data from one block of GPU memory to another.
Definition: CudaDnn.cs:6007
void mul_scalar(int n, double fAlpha, long hY)
Mutlipy each element of Y by a scalar.
Definition: CudaDnn.cs:7374
void scal(int n, double fAlpha, long hX, int nXOff=0)
Scales the data in X by a scaling factor.
Definition: CudaDnn.cs:6767
void max(int n, long hA, long hB, long hY)
Calculates the max of A and B and places the result in Y. This max is only computed on a per item bas...
Definition: CudaDnn.cs:7669
void FreeMemory(long hMem)
Free previously allocated GPU memory.
Definition: CudaDnn.cs:2517
void add_scalar(int n, double fAlpha, long hY)
Adds a scalar value to each element of Y.
Definition: CudaDnn.cs:7161
void scale_to_range(int n, long hX, long hY, double fMin, double fMax)
Scales the values in X and places the result in Y (can also run inline where X = Y).
Definition: CudaDnn.cs:6973
long AllocMemory(List< double > rg)
Allocate a block of GPU memory and copy a list of doubles to it.
Definition: CudaDnn.cs:2291
void sub(int n, long hA, long hB, long hY, int nAOff=0, int nBOff=0, int nYOff=0, int nB=0)
Subtracts B from A and places the result in Y.
Definition: CudaDnn.cs:7312
T[] SetPixel(long hMem, int nCount, bool bReturnOriginal, int nOffset, params Tuple< int, T >[] rgPixel)
Set a pixel value where each pixel is defined a set index, value tuple.
Definition: CudaDnn.cs:2933
void add(int n, long hA, long hB, long hC, long hY)
Adds A, B and C and places the result in Y.
Definition: CudaDnn.cs:7209
static ulong basetype_size(bool bUseHalfSize)
Returns the base type size in bytes.
Definition: CudaDnn.cs:1899
void axpy(int n, double fAlpha, long hX, long hY)
Multiply the vector X by a scalar and add the result to the vector Y.
Definition: CudaDnn.cs:6544
void transposeHW(int n, int c, int h, int w, long hSrc, long hDst)
Transpose a n*c number of matrices along the height and width dimensions. All matrices are in row-maj...
Definition: CudaDnn.cs:6716
Tuple< double, double, double, double > minmax(int n, long hA, long hWork1, long hWork2, bool bDetectNans=false, int nAOff=0)
Finds the minimum and maximum values within A.
Definition: CudaDnn.cs:7818
double[] GetMemoryDouble(long hMem, long lCount=-1)
Retrieves the GPU memory as an array of doubles.
Definition: CudaDnn.cs:2677
void channel_percentile(int nCount, int nOuterNum, int nChannels, int nInnerNum, long hX, long hY, double dfPercentile)
Calculates the percentile along axis = 0.
Definition: CudaDnn.cs:8361
void set(int nCount, long hHandle, double fVal, int nIdx=-1)
Set the values of GPU memory to a specified value of type
Definition: CudaDnn.cs:5897
double asum_double(int n, long hX, int nXOff=0)
Computes the sum of absolute values in X.
Definition: CudaDnn.cs:6871
T asum(int n, long hX, int nXOff=0)
Computes the sum of absolute values in X.
Definition: CudaDnn.cs:6901
void min(int n, long hA, long hB, long hY)
Calculates the min of A and B and places the result in Y. This min is only computed on a per item bas...
Definition: CudaDnn.cs:7702
T[] get(int nCount, long hHandle, int nIdx=-1)
Queries the GPU memory by copying it into an array of type 'T'.
Definition: CudaDnn.cs:5985
float[] GetMemoryFloat(long hMem, long lCount=-1)
Retrieves the GPU memory as an array of float.
Definition: CudaDnn.cs:2689
T dot(int n, long hX, long hY, int nXOff=0, int nYOff=0)
Computes the dot product of X and Y.
Definition: CudaDnn.cs:6847
The SyncedMemory manages the low-level connection between the GPU and host memory.
Definition: SyncedMemory.cs:18
bool HalfSize
Returns whether or not the sync memory is half-sized memory.
void async_gpu_push(long hStream, T[] rg)
Pushes the host data, previously set with set_cpu_data_locally(), to the GPU.
long gpu_data
Returns the handle to the GPU memory.
object Tag
Get/set data associated with the synced memory.
void set_gpu_data(long hData, long lCount, long lOffset)
Copies a new Memory Pointer within the low-level CudaDnnDLL where a Memory Pointer uses another alrea...
T[] mutable_cpu_data
Get/set the mutable host data.
long Copy(SyncedMemory< T > src, long hDstHostBuffer=0)
Copy another SyncedMemory into this one.
void Dispose()
Releases all GPU and host resources used.
Definition: SyncedMemory.cs:77
void SetData(T[] rgData, int nCount, bool bSetCount=true)
Sets the array of host data on the GPU and re-allocates the GPU memory if needed.
void Allocate(long lCount, bool bUseHalfSize=false)
Allocate a number of items in GPU memory and save the handle.
Definition: SyncedMemory.cs:92
long Capacity
Returns the total amount of GPU memory held by this SyncedMemory.
T GetAt(int nIdx)
Return a value at a given index.
long mutable_gpu_data
Returns the mutable handle to GPU data.
T[] update_cpu_data(long lCount=-1)
Updates the host data by copying the GPU data to the host data.
T[] cpu_data
Returns the data on the CPU that has already been transferred from GPU to CPU.
void ZeroAll()
Set all items in the GPU memory up to the Capacity, to zero.
void set_cpu_data_locally(T[] rg)
This does not place the data on the GPU - call async_gpu_push() to move it to the GPU.
long Count
Returns the current count of items in this SyncedMemory. Note, the Count may be less than the Capacit...
The BlobProto contains the descripion of a blob.
Definition: BlobProto.cs:15
List< float > data
Get/set the data as a List of float.
Definition: BlobProto.cs:180
List< double > double_diff
Get/set the diff as a List of double.
Definition: BlobProto.cs:171
BlobShape shape
Specifies the shape of the Blob.
Definition: BlobProto.cs:117
List< double > double_data
Get/set the data as a List of double.
Definition: BlobProto.cs:162
int? num
Specifies the number of inputs (such as images) in the Blob.
Definition: BlobProto.cs:126
List< float > diff
Get/set the diff as a List of float.
Definition: BlobProto.cs:189
int? height
Specifies the height of each input.
Definition: BlobProto.cs:144
int? channels
Specifies the number of images per input.
Definition: BlobProto.cs:135
int? width
Specifies the width of each input.
Definition: BlobProto.cs:153
Specifies the shape of a Blob.
Definition: BlobShape.cs:15
List< int > dim
The blob shape dimensions.
Definition: BlobShape.cs:93
Stores parameters used to apply transformation to the data layer's data.
COLOR_ORDER
Defines the color ordering used to tranform the input data.
The MyCaffe.basecode contains all generic types used throughout MyCaffe.
Definition: Annotation.cs:12
The MyCaffe.common namespace contains common MyCaffe classes.
Definition: BatchInput.cs:8
BLOB_TYPE
Defines the tpe of data held by a given Blob.
Definition: Interfaces.cs:62
The MyCaffe.param namespace contains parameters used to create models.
The MyCaffe namespace contains the main body of MyCaffe code that closesly tracks the C++ Caffe open-...
Definition: Annotation.cs:12