Распараллеливание вычислений в ABAP
Распараллеливание вычислений в ABAP (не Cloud, в Cloud есть своё отдельное API) выполняется либо через aRFC (pRFC) модули, либо через фоновые задания. Подробное описание первого сценария можно почитать тут. Чтобы каждый раз не дублировать код с обработкой стандартных функций, можно воспользоваться простым фреймворком для распараллеливания.
Демо программа (https://github.com/MikeSidorochkin/ABAP-Simple-Async-Framework/blob/main/zbc_async_demo.prog.abap):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 |
REPORT zbc_async_demo. CLASS lcl_task DEFINITION INHERITING FROM zcl_bc_async_task_base. PROTECTED SECTION. METHODS: start REDEFINITION, receive REDEFINITION. ENDCLASS. PARAMETERS: p_s_grp TYPE rzlli_apcl DEFAULT 'parallel_generators' MATCHCODE OBJECT spta_server_group, p_perc TYPE i DEFAULT 75. SELECTION-SCREEN: SKIP. PARAMETERS: p_calls TYPE i DEFAULT 20. CLASS lcl_task IMPLEMENTATION. METHOD start. CALL FUNCTION 'ZBC_PARALELL_TEST' STARTING NEW TASK mv_task_name DESTINATION IN GROUP mv_server_group CALLING receive_internal ON END OF TASK EXCEPTIONS communication_failure = 1 MESSAGE ev_message system_failure = 2 MESSAGE ev_message resource_failure = 3 OTHERS = 4. ev_subrc = sy-subrc. ENDMETHOD. METHOD receive. RECEIVE RESULTS FROM FUNCTION 'ZBC_PARALELL_TEST'. ENDMETHOD. ENDCLASS. START-OF-SELECTION. DATA(go_timer) = cl_abap_runtime=>create_hr_timer( ). DATA(gv_start_time) = go_timer->get_runtime( ). TRY. DATA(go_controller) = NEW zcl_bc_async_controller( it_server_groups = VALUE #( ( CONV #( p_s_grp ) ) ) iv_max_percent = p_perc ). DO p_calls TIMES. go_controller->add_task( NEW lcl_task( io_controller = go_controller iv_name = |{ sy-index }| ) ). ENDDO. go_controller->start( ). CATCH zcx_bc_async_base INTO DATA(go_exception). WRITE go_exception->get_text( ). STOP. ENDTRY. DATA(gt_tasks) = go_controller->get_tasks( ). WRITE: / 'Processes started: ', p_calls. ULINE. LOOP AT gt_tasks ASSIGNING FIELD-SYMBOL(<ls_task>). WRITE: / 'Task name: ', <ls_task>-name(5) , 'Start time: ', |{ <ls_task>-start_time TIMESTAMP = ENVIRONMENT }|, 'End time: ' , |{ <ls_task>-end_time TIMESTAMP = ENVIRONMENT }|. ENDLOOP. ULINE. DATA(gv_time) = VALUE t( ). gv_time = ( go_timer->get_runtime( ) - gv_start_time ) / 1000000. WRITE: /(50) 'Total time:', |{ gv_time TIME = USER }|. |
Для того чтобы распараллелить любую задачу необходимо создать RFC модуль в котором будет логика обработки некоторого блока данных, разделить массив обрабатываемых данных на пакеты/задачи и добавить их в контроллер.
Распараллеливание лучше запускать с опцией относительно процентной нагрузки на группу серверов. Если все таки было задано число используемых процессов и оно больше свободных на момент запуска, контроллер будет ожидать доступности ресурсов по таймауту, количество попыток задаётся отдельно.
Если не передавать процент и максимальное число процессов, программа автоматически выделит безопасное с точки зрения нагрузки на систему число ресурсов.