Параллельное вычисление хеша через несколько TransformBlocks приводит к беспорядку
818 просмотра
1 ответ
Я пытаюсь вычислить хэши для всего каталога, чтобы отслеживать изменения позже. Это относительно легко. Однако, если есть большие файлы, вычисления занимают слишком много времени, поэтому я использовал несколько многопоточности.
Благодаря узким местам ввода / вывода я должен прочитать файл с одним потоком, но я могу вычислить хэш для этого файла в нескольких потоках с одновременным вызовом методов TransformBlock. Проблема в том, что результат каждого вычисления различен - потому что все потоки обновляют один экземпляр хэш-алгоритма, они делают это беспорядочно.
public delegate void CalculateHashDelegate(byte[] buffer);
private MD5 md5;
private long completed_threads_hash;
private object lock_for_hash = new object();
`private string getMd5Hash(string file_path)
{
string file_to_be_hashed = file_path;
byte[] hash;
try
{
CalculateHashDelegate CalculateHash = AsyncCalculateHash;
md5 = MD5.Create();
using (Stream input = File.OpenRead(file_to_be_hashed))
{
int buffer_size = 0x4096;
byte[] buffer = new byte[buffer_size];
long part_count = 0;
completed_threads_hash = 0;
int bytes_read;
while ((bytes_read = input.Read(buffer, 0, buffer.Length)) == buffer_size)
{
part_count++;
IAsyncResult ar_hash = CalculateHash.BeginInvoke(buffer, CalculateHashCallback, CalculateHash);
}
// Wait for completing all the threads
while (true)
{
lock (completed_threads_lock)
{
if (completed_threads_hash == part_count)
{
md5.TransformFinalBlock(buffer, 0, bytes_read);
break;
}
}
}
hash = md5.Hash;
}
StringBuilder sb = new StringBuilder();
for (int i = 0; i < hash.Length; i++)
{
sb.Append(hash[i].ToString("x2"));
}
md5.Clear();
return sb.ToString();
}
catch (Exception ex)
{
Console.WriteLine("An exception was encountered during hashing file {0}. {1}.", file_to_be_hashed, ex.Message);
return ex.Message;
}
}
public void AsyncCalculateHash(byte[] buffer)
{
lock (lock_for_hash)
{
md5.TransformBlock(buffer, 0, buffer.Length, null, 0);
}
}
private void CalculateHashCallback(IAsyncResult ar_hash)
{
try
{
CalculateHashDelegate CalculateHash = ar_hash.AsyncState as CalculateHashDelegate;
CalculateHash.EndInvoke(ar_hash);
}
catch (Exception ex)
{
Console.WriteLine("Callback exception: ", ex.Message);
}
finally
{
lock (completed_threads_lock)
{
completed_threads_hash++;
}
}
}
Есть ли способ организовать процесс хеширования? Я не могу использовать .Net новее 3.5 и такие классы, как BackroundWorker и ThreadPool. Или, может быть, есть другой метод для параллельного вычисления хеша?
Автор: Leeder Источник Размещён: 13.11.2019 11:35Ответы (1)
2 плюса
Как правило, вы не можете использовать криптографические объекты в многопоточном коде. Проблема с методами хэширования заключается в том, что они полностью линейны - каждый блок хеширования зависит от текущего состояния, а состояние вычисляется с использованием всех предыдущих блоков. В общем, вы не можете сделать это для MD5.
Существует еще один процесс, который можно использовать, и он называется хеш-деревом или деревом Меркле . В основном вы выбираете размер блока и вычисляете хеш для блоков. Эти хэши объединяются и снова хэшируются. Если у вас очень много хэшей, вы можете создать дерево, как описано в статье в Википедии, на которую мы ссылались ранее. Конечно, полученный хэш отличается от просто MD5 и зависит от параметров конфигурации дерева хешей.
Обратите внимание, что MD5 был сломан. Вы должны использовать SHA-256 или SHA-512 / xxx (быстрее на 64-битных процессорах). Также обратите внимание, что часто скорость ввода-вывода является скорее препятствием, чем скоростью алгоритма хэширования, сводя на нет любые преимущества скорости в деревьях хэширования. Если у вас много файлов, вы также можете распараллелить хеширование на уровне файлов.
Автор: Maarten Bodewes Размещён: 18.10.2015 12:05Вопросы из категории :
- c# Преобразовать десятичную в двойную?
- c# Как рассчитать чей-то возраст в C #?
- c# Как вы сортируете словарь по значению?
- c# В чем разница между int и Integer в Java и C #?
- c# Как создать новый экземпляр объекта из Типа
- c# Datatable против Dataset
- multithreading Что такое состояние гонки?
- multithreading Что такое тупик?
- multithreading Что такое мьютекс?
- multithreading Как начать потоки в plain C?
- multithreading Потокобезопасный foreach перечисление списков
- multithreading Когда ключевое слово volatile должно использоваться в C #?
- hash Есть ли какая-либо функция хэш-кода в JavaScript?
- hash Есть ли фиксированная точка MD5, где md5 (x) == x?
- hash Какой тип данных использовать для поля хешированного пароля и какой длины?
- hash Почему Java hashCode () в String использует 31 в качестве множителя?
- hash Является ли «двойное хеширование» пароля менее безопасным, чем одноразовое хеширование?
- hash Как объединить хэши в Perl?