C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

VBでCRC32を高速で計算する方法 [3]

[トピック内 95 記事 (61 - 80 表示)]  << 0 | 1 | 2 | 3 | 4 >>

■82442 / inTopicNo.61)  Re[28]: VBでCRC32を高速で計算する方法
  
□投稿者/ ぎゅんぎゅ (51回)-(2017/01/10(Tue) 20:22:05)
ありがとうございます。

Public Sub New()
 #If Not NETCORE Then
  HashSizeValue = 32
 #End If
End Sub

を改良しました。

そしてもう一つのバグは
VBでのincrementの仕方が分からないので
offset = +1
crcLocal = table((crcLocal Xor input(offset)) And &HFF) Xor crcLocal >> 8

としました。
こうすると
Return New Byte() {CByte(_currentCrc >> 24), CByte(_currentCrc >> 16), CByte(_currentCrc >> 8), CByte(_currentCrc)}

のところでオーバーフローが発生してしまうのですが。

エラーが発生するということは、コードの呼び出し方はあっているのではないかと思いますが
どうでしょうか?
 
引用返信 編集キー/
■82443 / inTopicNo.62)  Re[29]: VBでCRC32を高速で計算する方法
□投稿者/ ぎゅんぎゅ (52回)-(2017/01/10(Tue) 20:47:28)
間違いました


offset += 1
crcLocal = table((crcLocal Xor input(offset)) And &HFF) Xor crcLocal >> 8


です
それでもオーバーフローが発生します
 
引用返信 編集キー/
■82444 / inTopicNo.63)  Re[30]: VBでCRC32を高速で計算する方法
□投稿者/ なちゃ (164回)-(2017/01/10(Tue) 21:26:59)
Return New Byte() {CByte(_currentCrc >> 24), CByte(_currentCrc >> 16), CByte(_currentCrc >> 8), CByte(_currentCrc)}

これらもそれぞれで&HFFでAndとってみてください。
多分Byte範囲声超えでオーバーフロー扱いになってます。
引用返信 編集キー/
■82445 / inTopicNo.64)  Re[31]: VBでCRC32を高速で計算する方法
□投稿者/ ぎゅんぎゅ (53回)-(2017/01/10(Tue) 21:51:32)
ありがとうございます。


Return New Byte() {CByte(_currentCrc >> 24) And &HFF, CByte(_currentCrc >> 16) And &HFF, CByte(_currentCrc >> 8) And &HFF, CByte(_currentCrc) And &HFF}


とするのでしょうか?
やはりオーバーフローになってしまうのですが
 
引用返信 編集キー/
■82446 / inTopicNo.65)  Re[32]: VBでCRC32を高速で計算する方法
□投稿者/ なちゃ (165回)-(2017/01/10(Tue) 21:52:48)
No82445 (ぎゅんぎゅ さん) に返信
> ありがとうございます。
>
>
> Return New Byte() {CByte(_currentCrc >> 24) And &HFF, CByte(_currentCrc >> 16) And &HFF, CByte(_currentCrc >> 8) And &HFF, CByte(_currentCrc) And &HFF}
>
>
> とするのでしょうか?
> やはりオーバーフローになってしまうのですが
>  

ちゃいます。
CByte(_currentCrc >> 24 And &HFF)
みたいにするんです。
引用返信 編集キー/
■82447 / inTopicNo.66)  Re[33]: VBでCRC32を高速で計算する方法
□投稿者/ ぎゅんぎゅ (54回)-(2017/01/10(Tue) 21:57:45)
ありがとうございます。
エラーなく実行できました。
しかし出てくる値が全く違うものになってしまいます。
何が原因でしょうか?
 
引用返信 編集キー/
■82448 / inTopicNo.67)  Re[34]: VBでCRC32を高速で計算する方法
□投稿者/ ぎゅんぎゅ (55回)-(2017/01/10(Tue) 21:58:47)
以下が改良したコードです。

Namespace Force_Crc32
Friend Class SafeProxy
Private Const Poly As UInteger = &HEDB88320UI

Private Shared ReadOnly _table As UInteger() = New UInteger(16 * 256 - 1) {}

Shared Sub New()
For i As UInteger = 0 To 255
Dim res As UInteger = i
For t As Integer = 0 To 15
For k As Integer = 0 To 7
res = If((res And 1) = 1, Poly Xor (res >> 1), (res >> 1))
Next
_table((t * 256) + i) = res
Next
Next
End Sub

Public Function Append(ByVal crc As UInteger, ByVal input As Byte(), ByVal offset As Integer, ByVal length As Integer) As UInteger
Dim crcLocal As UInteger = UInteger.MaxValue Xor crc

Dim table As UInteger() = _table
While length >= 16
crcLocal = table((15 * 256) + ((crcLocal Xor input(offset)) And &HFF)) _
Xor table((14 * 256) + (((crcLocal >> 8) Xor input(offset + 1)) And &HFF)) _
Xor table((13 * 256) + (((crcLocal >> 16) Xor input(offset + 2)) And &HFF)) _
Xor table((12 * 256) + (((crcLocal >> 24) Xor input(offset + 3)) And &HFF)) _
Xor table((11 * 256) + input(offset + 4)) _
Xor table((10 * 256) + input(offset + 5)) _
Xor table((9 * 256) + input(offset + 6)) _
Xor table((8 * 256) + input(offset + 7)) _
Xor table((7 * 256) + input(offset + 8)) _
Xor table((6 * 256) + input(offset + 9)) _
Xor table((5 * 256) + input(offset + 10)) _
Xor table((4 * 256) + input(offset + 11)) _
Xor table((3 * 256) + input(offset + 12)) _
Xor table((2 * 256) + input(offset + 13)) _
Xor table((1 * 256) + input(offset + 14)) _
Xor table((0 * 256) + input(offset + 15))
offset += 16
length -= 16
End While

'While System.Threading.Interlocked.Decrement(length) >= 0
While length >= 0
length -= 1
'crcLocal = table((crcLocal Xor input(System.Math.Max(System.Threading.Interlocked.Increment(offset), offset - 1))) And &HFF) Xor crcLocal >> 8
offset += 1
crcLocal = table((crcLocal Xor input(offset)) And &HFF) Xor crcLocal >> 8
End While
Return crcLocal Xor UInteger.MaxValue
End Function
End Class
End Namespace




Imports System
Imports System.Security.Cryptography

Namespace Force_Crc32
''' <summary>
''' Implementation of CRC-32.
''' This class supports several convenient static methods returning the CRC as UInt32.
''' </summary>
Public Class Crc32Algorithm
Inherits HashAlgorithm
Private _currentCrc As UInteger

''' <summary>
''' Initializes a new instance of the <see cref="Crc32Algorithm"/> class.
''' </summary>
Public Sub New()
#If Not NETCORE Then
HashSizeValue = 32
#End If
End Sub


''' <summary>
''' Computes CRC-32 from multiple buffers.
''' Call this method multiple times to chain multiple buffers.
''' </summary>
''' <param name="initial">
''' Initial CRC value for the algorithm. It is zero for the first buffer.
''' Subsequent buffers should have their initial value set to CRC value returned by previous call to this method.
''' </param>
''' <param name="input">Input buffer with data to be checksummed.</param>
''' <param name="offset">Offset of the input data within the buffer.</param>
''' <param name="length">Length of the input data in the buffer.</param>
''' <returns>Accumulated CRC-32 of all buffers processed so far.</returns>
Public Shared Function Append(ByVal initial As UInteger, ByVal input2 As Byte(), ByVal offset As Integer, ByVal length As Integer) As UInteger
If input2 Is Nothing Then
Throw New ArgumentNullException()
End If
If offset < 0 OrElse length < 0 OrElse offset + length > input2.Length Then
Throw New ArgumentOutOfRangeException("Selected range is outside the bounds of the input array")
End If
Return AppendInternal(initial, input2, offset, length)
End Function

''' <summary>
''' Computes CRC-3C from multiple buffers.
''' Call this method multiple times to chain multiple buffers.
''' </summary>
''' <param name="initial">
''' Initial CRC value for the algorithm. It is zero for the first buffer.
''' Subsequent buffers should have their initial value set to CRC value returned by previous call to this method.
''' </param>
''' <param name="input">Input buffer containing data to be checksummed.</param>
''' <returns>Accumulated CRC-32 of all buffers processed so far.</returns>
Public Shared Function Append(ByVal initial As UInteger, ByVal input As Byte()) As UInteger
If input Is Nothing Then
Throw New ArgumentNullException()
End If
Return AppendInternal(initial, input, 0, input.Length)
End Function

''' <summary>
''' Computes CRC-32 from input buffer.
''' </summary>
''' <param name="input">Input buffer with data to be checksummed.</param>
''' <param name="offset">Offset of the input data within the buffer.</param>
''' <param name="length">Length of the input data in the buffer.</param>
''' <returns>CRC-32 of the data in the buffer.</returns>
Public Shared Function Compute(ByVal input As Byte(), ByVal offset As Integer, ByVal length As Integer) As UInteger
Return Append(0, input, offset, length)
End Function

''' <summary>
''' Computes CRC-32 from input buffer.
''' </summary>
''' <param name="input">Input buffer containing data to be checksummed.</param>
''' <returns>CRC-32 of the buffer.</returns>
Public Shared Function Compute(ByVal input As Byte()) As UInteger
Return Append(0, input)
End Function

''' <summary>
''' Resets internal state of the algorithm. Used internally.
''' </summary>
Public Overrides Sub Initialize()
_currentCrc = 0
End Sub

''' <summary>
''' Appends CRC-32 from given buffer
''' </summary>
Protected Overrides Sub HashCore(ByVal input As Byte(), ByVal offset As Integer, ByVal length As Integer)
_currentCrc = AppendInternal(_currentCrc, input, offset, length)
End Sub

''' <summary>
''' Computes CRC-32 from <see cref="HashCore"/>
''' </summary>
Protected Overrides Function HashFinal() As Byte()
' Crc32 by dariogriffo uses big endian, so, we need to be compatible and return big endian too
Return New Byte() {CByte(_currentCrc >> 24 And &HFF), CByte(_currentCrc >> 16 And &HFF), CByte(_currentCrc >> 8 And &HFF), CByte(_currentCrc And &HFF)}
End Function

Private Shared ReadOnly _proxy As New SafeProxy()

Private Shared Function AppendInternal(ByVal initial As UInteger, ByVal input As Byte(), ByVal offset As Integer, ByVal length As Integer) As UInteger
If length > 0 Then
Return _proxy.Append(initial, input, offset, length)
Else
Return initial
End If
End Function
End Class
End Namespace

引用返信 編集キー/
■82449 / inTopicNo.68)  Re[35]: VBでCRC32を高速で計算する方法
□投稿者/ なちゃ (166回)-(2017/01/10(Tue) 22:14:54)
No82448 (ぎゅんぎゅ さん) に返信
> 以下が改良したコードです。
> 'While System.Threading.Interlocked.Decrement(length) >= 0
> While length >= 0
> length -= 1
> 'crcLocal = table((crcLocal Xor input(System.Math.Max(System.Threading.Interlocked.Increment(offset), offset - 1))) And &HFF) Xor crcLocal >> 8
> offset += 1
> crcLocal = table((crcLocal Xor input(offset)) And &HFF) Xor crcLocal >> 8
> End While

とりあえず

> While length >= 0


While length > 0
引用返信 編集キー/
■82450 / inTopicNo.69)  Re[36]: VBでCRC32を高速で計算する方法
□投稿者/ なちゃ (167回)-(2017/01/10(Tue) 22:24:36)
No82449 (なちゃ さん) に返信
> ■No82448 (ぎゅんぎゅ さん) に返信
>>以下が改良したコードです。
>> 'While System.Threading.Interlocked.Decrement(length) >= 0
>> While length >= 0
>> length -= 1
>> 'crcLocal = table((crcLocal Xor input(System.Math.Max(System.Threading.Interlocked.Increment(offset), offset - 1))) And &HFF) Xor crcLocal >> 8
>> offset += 1
>> crcLocal = table((crcLocal Xor input(offset)) And &HFF) Xor crcLocal >> 8
>> End While

これも逆順ですね。

>> offset += 1
>> crcLocal = table((crcLocal Xor input(offset)) And &HFF) Xor crcLocal >> 8

crcLocal = table((crcLocal Xor input(offset)) And &HFF) Xor crcLocal >> 8
offset += 1

引用返信 編集キー/
■82451 / inTopicNo.70)  Re[37]: VBでCRC32を高速で計算する方法
□投稿者/ ぎゅんぎゅ (56回)-(2017/01/10(Tue) 22:31:35)
なちゃ さん

ありがとうございます。

うまくいきました
同じ結果が得られました

しかもC#のDLLを使うよりも30%くらい速くなりました
前に同じコードをVBとC#で比較して
1.5〜2倍くらいC#の方が常に速い結果が得られていたのですが
DLLで読み込ませるとそうならないようですね

もう少しいろいろ試してみます。
 
引用返信 編集キー/
■82452 / inTopicNo.71)  Re[38]: VBでCRC32を高速で計算する方法
□投稿者/ なちゃ (168回)-(2017/01/10(Tue) 22:35:22)
No82451 (ぎゅんぎゅ さん) に返信
> なちゃ さん
>
> ありがとうございます。
>
> うまくいきました
> 同じ結果が得られました
>
> しかもC#のDLLを使うよりも30%くらい速くなりました
> 前に同じコードをVBとC#で比較して
> 1.5〜2倍くらいC#の方が常に速い結果が得られていたのですが
> DLLで読み込ませるとそうならないようですね
>
> もう少しいろいろ試してみます。
>  

なんかその辺はどうも怪しいですけどね。
実はDebugビルドになってたとかないですか?
こちらはC#の方がやや速かったですが。

引用返信 編集キー/
■82453 / inTopicNo.72)  Re[38]: VBでCRC32を高速で計算する方法
□投稿者/ ぎゅんぎゅ (57回)-(2017/01/10(Tue) 22:37:53)
間違いました

C# DLLの方が30%くらい速いです。

やはり計算量の多いコードはVBで書かずに
C#かC++で書いてDLL化した方が良いということでしょうか
 
引用返信 編集キー/
■82454 / inTopicNo.73)  Re[39]: VBでCRC32を高速で計算する方法
□投稿者/ なちゃ (169回)-(2017/01/10(Tue) 22:38:20)
No82452 (なちゃ さん) に返信
> なんかその辺はどうも怪しいですけどね。
> 実はDebugビルドになってたとかないですか?
> こちらはC#の方がやや速かったですが。

よく見るとこのライブラリstaticコンストラクタ使ってるので、細かくは見ていませんが、
場合によってはパフォーマンスに影響してるかもしれないですね。

引用返信 編集キー/
■82455 / inTopicNo.74)  Re[39]: VBでCRC32を高速で計算する方法
□投稿者/ なちゃ (170回)-(2017/01/10(Tue) 22:41:14)
No82453 (ぎゅんぎゅ さん) に返信
> 間違いました
>
> C# DLLの方が30%くらい速いです。
>
> やはり計算量の多いコードはVBで書かずに
> C#かC++で書いてDLL化した方が良いということでしょうか
>  

VBはオーバーフローチェックとか省けなかったりするので、余計な処理が入る可能性が高いです。
C#はましですが、C++よりは余計な処理が入るでしょう。

ちなみに実行速度は、以前のと比べた場合はどんな感じですか?

引用返信 編集キー/
■82456 / inTopicNo.75)  Re[40]: VBでCRC32を高速で計算する方法
□投稿者/ ぎゅんぎゅ (58回)-(2017/01/10(Tue) 22:48:13)
500MBを処理するのに


VBの旧CRC(integer) 4.0sec
VBの旧CRC(uinteger) 1.45sec
VBのMD5 1.2sec

VBの新CRC 0.84sec
C#DLL 0.59sec

でした。

劇的に速くなっています。

ところでこれってどういうアルゴリズムを使っているのでしょうか?
データ読込と計算を並列化しているのでしょうか?
コードを見れば分かると思ったのですが
見てもさっぱり何の処理をしているのかわかりませんでした。




引用返信 編集キー/
■82457 / inTopicNo.76)  Re[41]: VBでCRC32を高速で計算する方法
□投稿者/ なちゃ (171回)-(2017/01/10(Tue) 23:20:30)
No82456 (ぎゅんぎゅ さん) に返信
> 500MBを処理するのに
>
>
> VBの旧CRC(integer) 4.0sec
> VBの旧CRC(uinteger) 1.45sec
> VBのMD5 1.2sec
>
> VBの新CRC 0.84sec
> C#DLL 0.59sec
>
> でした。
>
> 劇的に速くなっています。
>
> ところでこれってどういうアルゴリズムを使っているのでしょうか?
> データ読込と計算を並列化しているのでしょうか?
> コードを見れば分かると思ったのですが
> 見てもさっぱり何の処理をしているのかわかりませんでした。

CRCの計算アルゴリズム(Crc32.NET)の方は、ループ展開による効率化ですね。

全体の処理としては、前にも書いたようにデータ読み込みと計算処理の並列化です。
読み込みと計算を順番にシーケンシャルに実行すると、読み込み実行、計算実行と順番に処理するため、読み込んでいる間は計算処理が動けません。

読み込みを実行後、バックグラウンドスレッドで読み込んだバッファの計算を開始し、平行して次のバッファへの読み込みを実行します。
こうすることで、計算処理がほぼ停止することなく全力で走り続けられるようになります。
※まあそれでもキャッシュに乗っていなければ読み込みはまず間に合わなくなりますが。
引用返信 編集キー/
■82458 / inTopicNo.77)  Re[40]: VBでCRC32を高速で計算する方法
□投稿者/ 魔界の仮面弁士 (1041回)-(2017/01/10(Tue) 23:50:06)
No82455 (なちゃ さん) に返信
> VBはオーバーフローチェックとか省けなかったりするので、

C# でいうところの checked / unchecked による部分的な切り替えは
できませんが、一応、コンパイラオプションで
整数のオーバーフローチェックを省略できるようにはなっています。VB6 も VB.NET も。
https://msdn.microsoft.com/ja-jp/library/aa711890.aspx
http://www.atmarkit.co.jp/fdotnet/vb6tonet/vb6tonet26/vb6tonet26_01.html#overflow

とはいえ、Express に同オプションがあるかはわかりません。
VBC.EXE で手動コンパイルする分には外せますけれども。
https://msdn.microsoft.com/ja-jp/library/key2x70f%28VS.80%29.aspx
引用返信 編集キー/
■82459 / inTopicNo.78)  Re[41]: VBでCRC32を高速で計算する方法
□投稿者/ なちゃ (172回)-(2017/01/11(Wed) 00:07:20)
No82458 (魔界の仮面弁士 さん) に返信
> ■No82455 (なちゃ さん) に返信
>>VBはオーバーフローチェックとか省けなかったりするので、
>
> C# でいうところの checked / unchecked による部分的な切り替えは
> できませんが、一応、コンパイラオプションで
> 整数のオーバーフローチェックを省略できるようにはなっています。VB6 も VB.NET も。
> https://msdn.microsoft.com/ja-jp/library/aa711890.aspx
> http://www.atmarkit.co.jp/fdotnet/vb6tonet/vb6tonet26/vb6tonet26_01.html#overflow
>
> とはいえ、Express に同オプションがあるかはわかりません。
> VBC.EXE で手動コンパイルする分には外せますけれども。
> https://msdn.microsoft.com/ja-jp/library/key2x70f%28VS.80%29.aspx

すっかり忘れてしまっていました。
そういえばありましたねこんなのが…
引用返信 編集キー/
■82460 / inTopicNo.79)  Re[42]: VBでCRC32を高速で計算する方法
□投稿者/ ぎゅんぎゅ (59回)-(2017/01/11(Wed) 10:11:50)
なちゃ さん

ありがとうございます。

ところでずっと気になっているのですが
MD5とこの高速CRCの計算の速度を比較した時、
一度読み込ませた後
(メモリにファイルが格納された状態)の二回目以降を比較すると上記で述べたように
2倍程度の高速化が見込めます。

しかし、通常CRCを求めるのに何度も同じファイルを計算しても意味がないので
一度しか求めることはしません。

そのため、一度500MBのファイルを2つコピーして、
PCを再起動し、メモリをクリアした状態でそれぞれ別のファイルに対して
MD5やCRCの計算を行って速度比較を行ったのですが
結果、いずれも4sec程度となり、全く差異が見られませんでした。

これって、結局、読込と計算を並列化したところで
HDDからの読込がボトルネックになっているので
ほとんど差異が表れないということでしょうか?

となってくると、CRCはMD5よりも桁数が小さい分、
異なるファイルでも同じ値になる確率が高く、安全性が低いので
結局MD5を使う方が良いのではないでしょうか?

これ以上は速度向上は見込めませんよね??







引用返信 編集キー/
■82461 / inTopicNo.80)  Re[43]: VBでCRC32を高速で計算する方法
 
□投稿者/ ぎゅんぎゅ (60回)-(2017/01/11(Wed) 10:21:11)
あと気になっているのですが、
一回目の読込と二回目以降の読込で
数倍程度、CRCやMD5の計算速度に違いが見られるのは間違いないです。

それでてっきりメモリにキャッシュされているのだと思っていたのですが
タスクマネージャーで4GB程度の大きなファイルを読み込ませる前と後のメモリ使用量を比較したのですが
全く違いは見られませんでした。

私の場合、OSの入ったCドライブをSSDを使い、データの入ったDドライブをHDDを使っているので
SSDのドライブに仮想ドライブとしてキャッシュされたのかと思い
ドライブの容量変化も比較しましたが
全く差異は見られませんでした。

それでは一体、どこにキャッシュされているのでしょうか?
そもそもキャッシュされているから二回目以降速くなる
というのは正しいのでしょうか?

 
引用返信 編集キー/

このトピックをツリーで一括表示

<前の20件 | 次の20件>
トピック内ページ移動 / << 0 | 1 | 2 | 3 | 4 >>

管理者用

- Child Tree -