This allows using the same codepath for both unix and windows for distributing new slices to code to threads. This also improves the performance on unix - instead of waiting for all the current threads to finish their current slice before handing out a new slice to each of them (where the threads that finish first will just wait instead of immediately getting a new slice to work on), we now use the same logic as on windows. In one setup, it improves the performance of encoding from ~920 fps to ~950 fps, and in another setup it goes from ~390 fps to ~660 fps. (These tests were done with the SM_ROWMB_SLICE mode, which heavily exercises the code for distributing new slices to the worker threads.) The extra WelsEventSignal call on windows where it isn't strictly necessary doesn't incur any measurable slowdown, so it is kept without any extra ifdefs to keep the code more readable and unified.
Showing the changes to codec/encoder/core/src/slice_multi_threading.cpp (1 of 3 files). Show all
Unified · Split
| @@ -351,10 +351,11 @@ int32_t RequestMtResource (sWelsEncCtx** ppCtx, SWelsSvcCodingParam* pCodingPara · 350 unmodified lines | |||
| 351 | 351 | ||
| 352 | MT_TRACE_LOG ((*ppCtx), WELS_LOG_INFO, "encpEncCtx= 0x%p\n", (void*) (*ppCtx)); | 352 | MT_TRACE_LOG ((*ppCtx), WELS_LOG_INFO, "encpEncCtx= 0x%p\n", (void*) (*ppCtx)); |
| 353 | 353 | ||
| 354 | char name[SEM_NAME_MAX] = {0}; | ||
| 355 | WELS_THREAD_ERROR_CODE err = 0; | ||
| 356 | |||
| 354 | iIdx = 0; | 357 | iIdx = 0; |
| 355 | while (iIdx < iThreadNum) { | 358 | while (iIdx < iThreadNum) { |
| 356 | char name[SEM_NAME_MAX] = {0}; | ||
| 357 | WELS_THREAD_ERROR_CODE err = 0; | ||
| 358 | pSmt->pThreadPEncCtx[iIdx].pWelsPEncCtx = (void*) (*ppCtx); | 359 | pSmt->pThreadPEncCtx[iIdx].pWelsPEncCtx = (void*) (*ppCtx); |
| 359 | pSmt->pThreadPEncCtx[iIdx].iSliceIndex = iIdx; | 360 | pSmt->pThreadPEncCtx[iIdx].iSliceIndex = iIdx; |
| 360 | pSmt->pThreadPEncCtx[iIdx].iThreadIndex = iIdx; | 361 | pSmt->pThreadPEncCtx[iIdx].iThreadIndex = iIdx; |
| @@ -386,6 +387,10 @@ int32_t RequestMtResource (sWelsEncCtx** ppCtx, SWelsSvcCodingParam* pCodingPara · 25 unmodified lines | |||
| 386 | ++ iIdx; | 387 | ++ iIdx; |
| 387 | } | 388 | } |
| 388 | 389 | ||
| 390 | WelsSnprintf (name, SEM_NAME_MAX, "scm%s", pSmt->eventNamespace); | ||
| 391 | err = WelsEventOpen (&pSmt->pSliceCodedMasterEvent, name); | ||
| 392 | MT_TRACE_LOG ((*ppCtx), WELS_LOG_INFO, "[MT] Open pSliceCodedMasterEvent named(%s) ret%d err%d\n", name, err, errno); | ||
| 393 | |||
| 389 | (*ppCtx)->pSliceBs = (SWelsSliceBs*)pMa->WelsMalloc (sizeof (SWelsSliceBs) * iMaxSliceNum, "pSliceBs"); | 394 | (*ppCtx)->pSliceBs = (SWelsSliceBs*)pMa->WelsMalloc (sizeof (SWelsSliceBs) * iMaxSliceNum, "pSliceBs"); |
| 390 | WELS_VERIFY_RETURN_PROC_IF (1, (NULL == (*ppCtx)->pSliceBs), FreeMemorySvc (ppCtx)) | 395 | WELS_VERIFY_RETURN_PROC_IF (1, (NULL == (*ppCtx)->pSliceBs), FreeMemorySvc (ppCtx)) |
| 391 | 396 | ||
| @@ -444,8 +449,8 @@ void ReleaseMtResource (sWelsEncCtx** ppCtx) { · 52 unmodified lines | |||
| 444 | if (NULL == pSmt) | 449 | if (NULL == pSmt) |
| 445 | return; | 450 | return; |
| 446 | 451 | ||
| 452 | char ename[SEM_NAME_MAX] = {0}; | ||
| 447 | while (iIdx < iThreadNum) { | 453 | while (iIdx < iThreadNum) { |
| 448 | char ename[SEM_NAME_MAX] = {0}; | ||
| 449 | // length of semaphore name should be system constrained at least on mac 10.7 | 454 | // length of semaphore name should be system constrained at least on mac 10.7 |
| 450 | #ifdef _WIN32 | 455 | #ifdef _WIN32 |
| 451 | if (pSmt->pThreadHandles != NULL && pSmt->pThreadHandles[iIdx] != NULL) | 456 | if (pSmt->pThreadHandles != NULL && pSmt->pThreadHandles[iIdx] != NULL) |
| @@ -467,6 +472,8 @@ void ReleaseMtResource (sWelsEncCtx** ppCtx) { · 15 unmodified lines | |||
| 467 | 472 | ||
| 468 | ++ iIdx; | 473 | ++ iIdx; |
| 469 | } | 474 | } |
| 475 | WelsSnprintf (ename, SEM_NAME_MAX, "scm%s", pSmt->eventNamespace); | ||
| 476 | WelsEventClose (&pSmt->pSliceCodedMasterEvent, ename); | ||
| 470 | 477 | ||
| 471 | WelsMutexDestroy (&pSmt->mutexSliceNumUpdate); | 478 | WelsMutexDestroy (&pSmt->mutexSliceNumUpdate); |
| 472 | WelsMutexDestroy (&((*ppCtx)->mutexEncoderError)); | 479 | WelsMutexDestroy (&((*ppCtx)->mutexEncoderError)); |
| @@ -864,6 +871,8 @@ WELS_THREAD_ROUTINE_TYPE CodingSliceThreadProc (void* arg) { · 391 unmodified lines | |||
| 864 | 871 | ||
| 865 | WelsEventSignal ( | 872 | WelsEventSignal ( |
| 866 | &pEncPEncCtx->pSliceThreading->pSliceCodedEvent[iEventIdx]); // mean finished coding current pSlice | 873 | &pEncPEncCtx->pSliceThreading->pSliceCodedEvent[iEventIdx]); // mean finished coding current pSlice |
| 874 | WelsEventSignal ( | ||
| 875 | &pEncPEncCtx->pSliceThreading->pSliceCodedMasterEvent); | ||
| 867 | } else { // for SM_DYN_SLICE parallelization | 876 | } else { // for SM_DYN_SLICE parallelization |
| 868 | SSliceCtx* pSliceCtx = pCurDq->pSliceEncCtx; | 877 | SSliceCtx* pSliceCtx = pCurDq->pSliceEncCtx; |
| 869 | const int32_t kiPartitionId = iThreadIdx; | 878 | const int32_t kiPartitionId = iThreadIdx; |
| @@ -967,6 +976,7 @@ WELS_THREAD_ROUTINE_TYPE CodingSliceThreadProc (void* arg) { · 97 unmodified lines | |||
| 967 | break; | 976 | break; |
| 968 | 977 | ||
| 969 | WelsEventSignal (&pEncPEncCtx->pSliceThreading->pSliceCodedEvent[iEventIdx]); // mean finished coding current pSlice | 978 | WelsEventSignal (&pEncPEncCtx->pSliceThreading->pSliceCodedEvent[iEventIdx]); // mean finished coding current pSlice |
| 979 | WelsEventSignal (&pEncPEncCtx->pSliceThreading->pSliceCodedMasterEvent); | ||
| 970 | } | 980 | } |
| 971 | } | 981 | } |
| 972 | #ifdef _WIN32 | 982 | #ifdef _WIN32 |