Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions .github/workflows/CI.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,18 @@ jobs:
cmake -A x64 ..
cmake --build . --config Release -j 4

windows-arm:
runs-on: windows-11-arm
steps:
- uses: actions/checkout@v4
with:
submodules: 'recursive'
- name: build
run: |
mkdir build; cd build
cmake -A arm64 ..
cmake --build . --config Release -j 4

ubuntu:
runs-on: ubuntu-latest
steps:
Expand Down
30 changes: 29 additions & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -120,8 +120,36 @@ jobs:
name: ${{ env.PACKAGENAME }}
path: ${{ env.PACKAGENAME }}.zip

windows-arm:
needs: [setup]
runs-on: windows-11-arm
env:
UseMultiToolTask: true
PACKAGENAME: ${{ needs.setup.outputs.APPNAME }}-${{ needs.setup.outputs.VERSION }}-windows-arm64
steps:
- uses: actions/checkout@v4
with:
submodules: 'recursive'
- name: build
run: |
mkdir build; cd build
cmake -A arm64 ..
cmake --build . --config Release -j 4
- name: package
run: |
mkdir ${{ env.PACKAGENAME }}
Copy-Item -Verbose -Path "README.md" -Destination "${{ env.PACKAGENAME }}"
Copy-Item -Verbose -Path "LICENSE" -Destination "${{ env.PACKAGENAME }}"
Copy-Item -Verbose -Path "build\Release\${{ needs.setup.outputs.APPNAME }}.exe" -Destination "${{ env.PACKAGENAME }}"
7z a -r ${{ env.PACKAGENAME }}.zip ${{ env.PACKAGENAME }}
- name: upload
uses: actions/upload-artifact@v4
with:
name: ${{ env.PACKAGENAME }}
path: ${{ env.PACKAGENAME }}.zip

release:
needs: [setup, ubuntu, macos, windows]
needs: [setup, ubuntu, macos, windows, windows-arm]
runs-on: ubuntu-latest
steps:
- name: download
Expand Down
97 changes: 95 additions & 2 deletions vkpeak.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,16 @@
// vkpeak implemented with ncnn library

#include <stdio.h>
#include <stdlib.h>

#ifdef _WIN32
#include <conio.h>
#include <io.h>
#include <windows.h>
#include <tlhelp32.h>
#include <psapi.h>
#endif

#include <benchmark.h>
#include <command.h>
#include <gpu.h>
Expand Down Expand Up @@ -2320,9 +2331,51 @@ static double vkpeak(int device_id, int storage_type, int arithmetic_type, int p
return max_gflops;
}

#ifdef _WIN32
static int is_running_in_console()
{
if (!_isatty(_fileno(stdin)))
return 0;

HWND consoleWindow = GetConsoleWindow();
if (consoleWindow == NULL)
return 0;

DWORD currentProcessId = GetCurrentProcessId();
DWORD parentProcessId = 0;

HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (hSnapshot == INVALID_HANDLE_VALUE)
return 0;

PROCESSENTRY32 pe32;
pe32.dwSize = sizeof(PROCESSENTRY32);

// Find parent process ID
if (Process32First(hSnapshot, &pe32)) {
do {
if (pe32.th32ProcessID == currentProcessId) {
parentProcessId = pe32.th32ParentProcessID;
break;
}
} while (Process32Next(hSnapshot, &pe32));
}
CloseHandle(hSnapshot);

if (parentProcessId == 0)
return 0;

HANDLE hParent = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, parentProcessId);
if (hParent == NULL)
return 0;

return 1;
}
#endif // _WIN32

int main(int argc, char** argv)
{
if (argc != 2)
if (argc != 1 && argc != 2)
{
fprintf(stderr, "Usage: %s [device_id]\n", argv[0]);

Copilot AI May 27, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The usage message 'Usage: %s [device_id]' does not clearly convey that running the program with no arguments is valid. Consider updating the message to indicate that the device_id parameter is optional when no argument is provided.

Suggested change
fprintf(stderr, "Usage: %s [device_id]\n", argv[0]);
fprintf(stderr, "Usage: %s [device_id] (device_id is optional; defaults to the first available device if not provided)\n", argv[0]);

Copilot uses AI. Check for mistakes.
return -1;
Expand All @@ -2337,7 +2390,7 @@ int main(int argc, char** argv)
return -1;
}

const int device_id = atoi(argv[1]);
const int device_id = argc == 2 ? atoi(argv[1]) : ncnn::get_default_gpu_index();
if (device_id < 0 || device_id >= gpu_count)
{
fprintf(stderr, "No vulkan device for %d\n", device_id);
Expand All @@ -2351,6 +2404,18 @@ int main(int argc, char** argv)
return -1;
}

if (argc == 1)
{
fprintf(stderr, "Available devices:\n");

for (int i = 0; i < gpu_count; i++)
{
fprintf(stderr, "%d = %s\n", i, ncnn::get_gpu_info(i).device_name());
}

fprintf(stderr, "Device %d will be used\n\n", device_id);
}

fprintf(stderr, "device = %s\n", ncnn::get_gpu_info(device_id).device_name());

// device_id = 0
Expand Down Expand Up @@ -2389,5 +2454,33 @@ int main(int argc, char** argv)

ncnn::destroy_gpu_instance();

#ifdef _WIN32
if (!is_running_in_console())
{
fprintf(stderr, "\nPress any key to continue...\n");

HANDLE hStdin = GetStdHandle(STD_INPUT_HANDLE);

// mltiple flush strategy
FlushConsoleInputBuffer(hStdin);
while (_kbhit()) _getch();
fflush(stdin);

// delay to ensure all input is processed
Sleep(100);

// flush again
FlushConsoleInputBuffer(hStdin);
while (_kbhit()) _getch();

// use low-level API to ensure waiting for new input
INPUT_RECORD record;
DWORD read;
do {
ReadConsoleInput(hStdin, &record, 1, &read);
} while (record.EventType != KEY_EVENT || !record.Event.KeyEvent.bKeyDown);
}
#endif // _WIN32

return 0;
}