Uploading data to D3D12 PBO from WSL 2 get very slow performance.

lei sun 0 信誉分
2025-01-22T06:21:32.0066667+00:00

Here is the translation of your text into English:


I uploaded data to a DirectX PBO in WSL 2, and the code is shown below. The performance is very slow; uploading 512 * 512 * 274 * 2 = 143,654,912 bytes took 470 milliseconds. I recorded a kernel trace log and, after analysis, extracted 120 functions with excessively long execution times (the log is attached). There are two scenarios:

  1. After returning to user mode from a page fault interrupt, the execution time of the exit_to_user_mode_prepare function is exceptionally long, ranging from 1 to 10 milliseconds (normally it should be less than 1 microsecond).
  2. During task switching in the idle process scheduler, when the CPU time slice is switched to another process, the execution time of the default_idle function is also exceptionally long, ranging from 1 to 10 milliseconds (normally it should be less than 1 microsecond).

These two scenarios combined account for most of the memcpy time, totaling 430 milliseconds, with the overall copy time being approximately 470–500 milliseconds. Moreover, these kernel activities are serialized and run on different CPU cores.

My WSL 2 environment is as follows:


wsl --version

WSL version: 2.3.26.0

Kernel version: 5.15.167.4-1

WSLg version: 1.0.65

MSRDC version: 1.2.5620

Direct3D version: 1.611.1-81528511

DXCore version: 10.0.26100.1-240331-1435.ge-release

Windows version: 10.0.19044.5371

The code is as follows:


size_t dataSize = 512 * 512 * 274 * 2;

BYTE* data = new BYTE[dataSize];

D3D12_HEAP_PROPERTIES pboHeapProperties = CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_CUSTOM);

pboHeapProperties.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_WRITE_BACK;

pboHeapProperties.MemoryPoolPreference = D3D12_MEMORY_POOL_L0;

// Create PBO (Pixel Buffer Object)

D3D12_RESOURCE_DESC pboResourceDesc = CD3DX12_RESOURCE_DESC::Buffer(dataSize);

ComPtr<ID3D12Resource> pboBuffer;

CHK(device->CreateCommittedResource(

    &pboHeapProperties,

    D3D12_HEAP_FLAG_NONE,

    &pboResourceDesc,

    D3D12_RESOURCE_STATE_COMMON,

    nullptr,

    IID_PPV_ARGS(&pboBuffer)

));

// Upload data to PBO

void* pPBOData;

CHK(pboBuffer->Map(0, nullptr, &pPBOData));

auto start = std::chrono::high_resolution_clock::now();

memcpy(pPBOData, data, dataSize);

auto end = std::chrono::high_resolution_clock::now();

auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();

std::cout << "mesa pbo memcpy: " << duration << " ms" << std::endl;

pboBuffer->Unmap(0, nullptr);

delete[] data;

The log of functions with excessively long execution times is as follows:


Line 14596 -    main-8596    [005] d.... 59090.531799: exit_to_user_mode_prepare <-irqentry_exit_to_user_mode

Line 14597 -    main-8596    [005] d.... 59090.536728: irq_enter_rcu <-sysvec_hyperv_stimer0

Line 14963 -  <idle>-0       [004] d.... 59090.536811: default_idle <-default_idle_call

Line 14964 -    main-8596    [005] ..... 59090.538477: down_read_trylock <-do_user_addr_fault

Line 14988 -    main-8596    [005] d.... 59090.538480: exit_to_user_mode_prepare <-irqentry_exit_to_user_mode

Line 14989 -  <idle>-0       [000] d.... 59090.541368: irq_enter_rcu <-sysvec_hyperv_stimer0

Line 15380 -  <idle>-0       [003] d.... 59090.541408: default_idle <-default_idle_call

Line 15381 -    main-8596    [005] ..... 59090.545148: down_read_trylock <-do_user_addr_fault

Line 15405 -    main-8596    [005] d.... 59090.545154: exit_to_user_mode_prepare <-irqentry_exit_to_user_mode

Line 15406 -    main-8596    [005] d.... 59090.546740: irq_enter_rcu <-sysvec_hyperv_stimer0

Line 15822 -  <idle>-0       [002] d.... 59090.546819: default_idle <-default_idle_call

Line 15823 -  <idle>-0       [000] d.... 59090.551491: irq_enter_rcu <-sysvec_hyperv_stimer0

Line 16239 -    main-8596    [005] d.... 59090.551784: exit_to_user_mode_prepare <-irqentry_exit_to_user_mode

Line 16240 -  <idle>-0       [004] d.... 59090.556749: irq_enter_rcu <-sysvec_hyperv_stimer0

Line 16986 -  <idle>-0       [000] d.... 59090.556811: default_idle <-default_idle_call

Line 16987 -    main-8596    [005] ..... 59090.558568: down_read_trylock <-do_user_addr_fault

Line 17011 -    main-8596    [005] d.... 59090.558573: exit_to_user_mode_prepare <-irqentry_exit_to_user_mode

Line 17012 -  <idle>-0       [003] d.... 59090.561637: irq_enter_rcu <-sysvec_hyperv_stimer0

Line 17403 -  <idle>-0       [003] d.... 59090.561680: default_idle <-default_idle_call

Line 17404 -    main-8596    [005] ..... 59090.565168: down_read_trylock <-do_user_addr_fault

Line 17429 -    main-8596    [005] d.... 59090.565172: exit_to_user_mode_prepare <-irqentry_exit_to_user_mode

Line 17430 -    main-8596    [005] d.... 59090.566737: irq_enter_rcu <-sysvec_hyperv_stimer0

Line 18087 -  <idle>-0       [004] d.... 59090.566891: default_idle <-default_idle_call

Line 18088 -  <idle>-0       [003] d.... 59090.571774: irq_enter_rcu <-sysvec_hyperv_stimer0

Line 18504 -    main-8596    [005] d.... 59090.571965: exit_to_user_mode_prepare <-irqentry_exit_to_user_mode

Line 18505 -    main-8596    [005] d.... 59090.576734: irq_enter_rcu <-sysvec_hyperv_stimer0

Line 18667 -  <idle>-0       [000] d.... 59090.576790: default_idle <-default_idle_call

Line 18668 -    main-8596    [005] ..... 59090.578686: down_read_trylock <-do_user_addr_fault

Line 18692 -    main-8596    [005] d.... 59090.578691: exit_to_user_mode_prepare <-irqentry_exit_to_user_mode

Line 18693 -  <idle>-0       [003] d.... 59090.581938: irq_enter_rcu <-sysvec_hyperv_stimer0

Line 19084 -  <idle>-0       [000] d.... 59090.581979: default_idle <-default_idle_call

Line 19085 -    main-8596    [005] ..... 59090.585449: down_read_trylock <-do_user_addr_fault

Line 19109 -    main-8596    [005] d.... 59090.585454: exit_to_user_mode_prepare <-irqentry_exit_to_user_mode

Line 19110 -    main-8596    [005] d.... 59090.586743: irq_enter_rcu <-sysvec_hyperv_stimer0

Line 19544 -  <idle>-0       [004] d.... 59090.586804: default_idle <-default_idle_call

Line 19545 -  <idle>-0       [003] d.... 59090.592042: irq_enter_rcu <-sysvec_hyperv_stimer0

Line 19961 -    main-8596    [005] d.... 59090.592175: exit_to_user_mode_prepare <-irqentry_exit_to_user_mode

Line 19962 -    main-8596    [005] d.... 59090.596734: irq_enter_rcu <-sysvec_hyperv_stimer0

Line 20250 -  <idle>-0       [004] d.... 59090.596831: default_idle <-default_idle_call

Line 20251 -    main-8596    [005] ..... 59090.598873: down_read_trylock <-do_user_addr_fault

Line 20275 -    main-8596    [005] d.... 59090.598876: exit_to_user_mode_prepare <-irqentry_exit_to_user_mode

Line 20276 -  <idle>-0       [000] d.... 59090.602174: irq_enter_rcu <-sysvec_hyperv_stimer0

Line 20786 -  <idle>-0       [003] d.... 59090.602217: default_idle <-default_idle_call

Line 20787 -    main-8596    [005] ..... 59090.605744: down_read_trylock <-do_user_addr_fault

Line 20964 -    main-8596    [005] d.... 59090.606776: exit_to_user_mode_prepare <-irqentry_exit_to_user_mode

Line 20965 -  <idle>-0       [000] d.... 59090.612332: irq_enter_rcu <-sysvec_hyperv_stimer0

Line 21424 -    main-8596    [005] d.... 59090.612445: exit_to_user_mode_prepare <-irqentry_exit_to_user_mode

Line 21425 -  <idle>-0       [002] d.... 59090.614087: irq_enter_rcu <-sysvec_hyperv_stimer0

Line 21611 -  <idle>-0       [002] d.... 59090.614121: default_idle <-default_idle_call

Line 21612 -    main-8596    [005] d.... 59090.616729: irq_enter_rcu <-sysvec_hyperv_stimer0

Line 21905 -  <idle>-0       [004] d.... 59090.616822: default_idle <-default_idle_call

Line 21906 -    main-8596    [005] ..... 59090.619251: down_read_trylock <-do_user_addr_fault

Line 21930 -    main-8596    [005] d.... 59090.619257: exit_to_user_mode_prepare <-irqentry_exit_to_user_mode

Line 21931 -  <idle>-0       [000] d.... 59090.622507: irq_enter_rcu <-sysvec_hyperv_stimer0

Line 22341 -  <idle>-0       [003] d.... 59090.622554: default_idle <-default_idle_call

Line 22342 -  <idle>-0       [000] d.... 59090.625236: irq_enter_rcu <-sysvec_hyperv_stimer0

Line 22936 -    main-8596    [005] d.... 59090.626742: exit_to_user_mode_prepare <-irqentry_exit_to_user_mode

Line 22937 -  <idle>-0       [001] d.... 59090.632274: irq_enter_rcu <-sysvec_hyperv_stimer0

Line 23587 -    main-8596    [005] d.... 59090.632729: exit_to_user_mode_prepare <-irqentry_exit_to_user_mode

Line 23588 -    main-8596    [005] d.... 59090.636762: irq_enter_rcu <-sysvec_hyperv_stimer0

Line 23659 -    main-8596    [005] d.... 59090.636773: exit_to_user_mode_prepare <-irqentry_exit_to_user_mode

Line 23660 -    main-8596    [005] ..... 59090.639431: down_read_trylock <-do_user_addr_fault

Line 23684 -    main-8596    [005] d.... 59090.639435: exit_to_user_mode_prepare <-irqentry_exit_to_user_mode

Line 23685 -  <idle>-0       [003] d.... 59090.642740: irq_enter_rcu <-sysvec_hyperv_stimer0

Line 24185 -  <idle>-0       [000] d.... 59090.642808: default_idle <-default_idle_call

Line 24186 -    main-8596    [005] ..... 59090.646261: down_read_trylock <-do_user_addr_fault

Line 24282 -    main-8596    [005] d.... 59090.646790: exit_to_user_mode_prepare <-irqentry_exit_to_user_mode

Line 24283 -  <idle>-0       [003] d.... 59090.652844: irq_enter_rcu <-sysvec_hyperv_stimer0

Line 24742 -    main-8596    [005] d.... 59090.652964: exit_to_user_mode_prepare <-irqentry_exit_to_user_mode

Line 24743 -    main-8596    [005] d.... 59090.656738: irq_enter_rcu <-sysvec_hyperv_stimer0

Line 24814 -    main-8596    [005] d.... 59090.656750: exit_to_user_mode_prepare <-irqentry_exit_to_user_mode

Line 24815 -    main-8596    [005] ..... 59090.659599: down_read_trylock <-do_user_addr_fault

Line 24839 -    main-8596    [005] d.... 59090.659604: exit_to_user_mode_prepare <-irqentry_exit_to_user_mode

Line 24840 -  <idle>-0       [003] d.... 59090.662976: irq_enter_rcu <-sysvec_hyperv_stimer0

Line 25274 -  <idle>-0       [000] d.... 59090.663091: default_idle <-default_idle_call

Line 25275 -    main-8596    [005] ..... 59090.666356: down_read_trylock <-do_user_addr_fault

Line 25371 -    main-8596    [005] d.... 59090.666748: exit_to_user_mode_prepare <-irqentry_exit_to_user_mode

Line 25372 -    main-8596    [005] ..... 59090.673042: down_read_trylock <-do_user_addr_fault

Line 25831 -  <idle>-0       [000] d.... 59090.673247: default_idle <-default_idle_call

Line 25832 -    main-8596    [005] d.... 59090.676738: irq_enter_rcu <-sysvec_hyperv_stimer0

Line 25903 -    main-8596    [005] d.... 59090.676749: exit_to_user_mode_prepare <-irqentry_exit_to_user_mode

Line 25904 -    main-8596    [005] ..... 59090.679784: down_read_trylock <-do_user_addr_fault

Line 25928 -    main-8596    [005] d.... 59090.679789: exit_to_user_mode_prepare <-irqentry_exit_to_user_mode

Line 25929 -  <idle>-0       [003] d.... 59090.683300: irq_enter_rcu <-sysvec_hyperv_stimer0

Line 26429 -  <idle>-0       [000] d.... 59090.683411: default_idle <-default_idle_call

Line 26430 -    main-8596    [005] ..... 59090.686380: down_read_trylock <-do_user_addr_fault

Line 26527 -    main-8596    [005] d.... 59090.686742: exit_to_user_mode_prepare <-irqentry_exit_to_user_mode

Line 26528 -    main-8596    [005] ..... 59090.693073: down_read_trylock <-do_user_addr_fault

Line 26987 -  <idle>-0       [000] d.... 59090.693533: default_idle <-default_idle_call

Line 26988 -    main-8596    [005] d....
Windows
Windows
Microsoft 操作系统系列,可跨个人计算机、平板电脑、笔记本电脑、手机、物联网设备、独立混合现实头戴显示设备、大型协作屏幕和其他设备运行。
581 个问题
Windows API - Win32
Windows API - Win32
一组适用于桌面和服务器应用程序的核心 Windows 应用程序编程接口 (API)。 以前称为 Win32 API。
135 个问题
{count} 票

你的答案

问题作者可以将答案标记为“接受的答案”,这有助于用户了解已解决作者问题的答案。