C#, Программирование

Ускорение DS-алгоритмов с помощью вставок на C#

Время прочтения: 2 мин.

Во время очередного DataScienceChallenge появился задача, которую можно описать так: необходимо реализовать алгоритм Process Mining, известный как Heuristic Miner. Так как это соревнование, значит, нужно чтобы алгоритм отработал как можно быстрее. Но как заставить алгоритм отработать “пятилетку за четыре года”? В DS-коммьюнити самым популярным языком является Python, однако по ряду причин, как то динамическая типизация, он имеет проблемы с оптимизацией скорости выполнения. И тут в голову пришла мыслишка: а что если… использовать более “скоростной” язык?

Так как по условиям соревнования от нас требовался исполняемый код на Python, было принято “соломоново” решение: запускать написанное на C# приложение напрямую из “питоновского” скрипта.

В итоге задача свелась к следующему:

  • Работа через консоль
    • Задание параметров для майнера
  • C#
    • Прогон алгоритма
    • Вывод результатов в консоль
  • Python
    • Запуск C# кода и передача параметров для майнера
    • Изменение прав на исполнение файла
    • Перехват вывода из консоли
    • Форматирование

Ну что же, вот и настало время интеграции C# и Python.

Итак, вывод в консоль результата С#-приложения:

Задача усложняется тем, что код будет выполняться через Docker-контейнеры на Linux. В связи с этим пришлось перекомплировать проект под Linux-x64, выдать себе права на выполнение C#-приложения, и провести форматирование полученного результата, который в силу особенностей операционной системы будет отличаться для Linux.
Исполняемый код на Python:

from subprocess import run
import json 
import os 
def apply_hue_miner(log_df, dependency_thresh=0.65, and_measure_thresh=0.65, dfg_pre_cleaning_noise_thresh=0.05): 
    cur_dir = os.getcwd() 
    log_dir = cur_dir+'/input/logs.csv' os.system('chmod +x ' + cur_dir + '/program/HeuristicMiner’) 
    output = run([cur_dir+'/program/HeuristicMiner', str(dependency_thresh), 
			  str(and_measure_thresh), 
			  str(dfg_pre_cleaning_noise_thresh), 
			  log_dir], capture_output=True).stdout 
    output = output.decode("utf-8") print(output.split('\n')[0]) 
    nodes = eval('['+output.split('\n')[0]+']’) 
    edges_t = '{'+output.split('\n')[1].replace(")'", ")").replace("'(", "(") + '}'
    edges = json.loads(edges_t) 
    edges = {eval(k): float(v) for k, v in edges.items()} 
    
   return {'nodes': nodes, 'edges': edges} 

По итогу оказалось, что код на C# отработал в 2 раза быстрее, чем аналогичная реализация алгоритма на Python. Так что, вполне возможно, вставки в ваш код, написанные на C#, смогут значительно ускорить реализуемые Вами алгоритмы.

Советуем почитать