Snapdragon™ 功率优化 SDK 为程序员提供了一个高级接口来表达预期的功率设置。 功率优化 SDK 将此信息提供给系统,因此它可以为应用程序选择最佳性能/功率点。 换句话说,功率接口与系统现有的功率和温度控制机制协作但不取代它。 所有 API 函数都向系统提供提示,不保证设备状态会更改为请求的状态。 根据其他正在运行的应用程序、设备温度和其他因素,内核数量和频率可能与要求的不同。 也就是说,明智地使用这些 API 可以帮助减少由于热限制导致的应用程序性能下降。
要被包括在C ++代码,以使用Power API下面的头文件的需求:
#include <qspower/power.hh>
还有一个 C 版本的 Power API,它在以下头文件中声明:
#include <qspower/power.h>
Snapdragon™ 功耗优化 SDK 分为两组 API:静态和动态。
在给定应用程序状态的情况下,静态模式 API 有助于程序员确切知道性能/功率点应该是什么。 在这种情况下,Power Optimization SDK 定义了几种可供程序员选择的静态功耗模式,并且运行时将保持该性能/功耗模式,直到程序员对其进行更改。
当应用程序表现出重复模式时,可以使用动态模式 API,例如,视频游戏的主循环或用于检测特征的图像库的遍历,并且程序员知道预期的吞吐量指标。 在这种情况下,Power Optimization SDK 可以根据动态功耗模式的指标动态调节内核数量和频率。
以下部分将介绍骁龙™ 功耗优化 SDK 提供的各种 API。
Snapdragon™ 功率优化 SDK 提供 qspower_init() 和 qspower_terminate() 函数来正确初始化和清理功率优化 SDK 基础架构内部。
应在调用静态或动态功率 API 之前调用 qspower_init() 以表达预期的功率设置。 在应用程序终止之前调用 qspower_terminate() 很重要。
功耗优化 SDK 提供了一组预定义的静态模式,以适应多个性能/功耗操作点。
除了选择预定义的静态模式,功率优化 SDK 还允许在特定设备上设置功率模式:CPU 大核、CPU 小核或 GPU。 qspower::device_set{} 对象聚合用户打算应用功率模式的所有设备。
选择功率模式只需要调用函数 qspower::request_mode(desired_mode, duration, device_set)。 请注意,duration 和 device_set 是可选的,默认情况下 device_set 设置为 CPU(大内核和小内核,如果可用),并且持续时间设置为无限期,直到发起下一个功率模式请求。
下面的例子展示了如何在计算向量加法时使用窗口模式设置CPU大核在特定频率范围内运行。
1 #include <random>
2 #include <vector>
3 #include <qspower/power.hh>
4
5 // Perform a vector addition reducing the power consumption
6 // by using the static window power mode
7 int main()
8 {
9 const size_t N = 100;
10 std::vector<float> a(N), b(N), c(N);
11 std::random_device random_device;
12 std::mt19937 generator(random_device());
13 const float min_value = -1024.0, max_value = 1024.0;
14 std::uniform_real_distribution<float> dist(min_value, max_value);
15
16 const float alpha = 0.2f; // multiplicative factor
17
18 qspower::init();
19
20 // request window mode of 40% to 50% frequency on cpu big cores for an indefinite period of time
21 qspower::request_mode(qspower::mode::window(40, 50),
qspower::device_set{ qspower::device_type::cpu_big });
22
23 // Initialize the source arrays with random numbers
24 for (size_t i = 0; i < N; i++)
25 {
26 a[i] = dist(generator);
27 b[i] = dist(generator);
28 }
29
30 // computation, vector addition
31 for (size_t i = 0; i < N; i++)
32 {
33 c[i] = alpha * a[i] + b[i];
34 }
35
36 // return the system to the normal power state
37 qspower::request_mode(qspower::mode::normal);
38
39 qspower::terminate();
40
41 return 0;
42 }
动态功率 API 运行一个反馈回路,该回路将自我调节系统以保持预期的性能水平,同时尽量减少功耗。 为了获得最佳结果,此 API 要求应用程序具有可预测的行为。
通过输入“loop”将执行work.Inside主循环之前设置与功能qspower预期性能目标:: set_goal(desired_target)自动功耗最小化启动,应用程序必须测量应用程序的性能,然后通过测量值在功率优化SDK与qspower的帮助::规范(measured_值)。 使用目标值和测量值,运行时间将调整系统以最小化功率。 在循环结束时,应用程序应调用qspower :: clear_goal()。
注意
在此版本的 Snapdragon™ 功率优化 SDK 中,仅在 CPU 大内核上支持动态功率 API
下一个示例演示了针对特定迭代次数重复添加两个向量,同时使用动态 Power API 来调节在 1 毫秒内处理向量中的元素数量。
1 #include <algorithm>
2 #include <chrono>
3 #include <random>
4 #include <vector>
5 #include <qspower/power.hh>
6
7 // Perform vector addition operation within a loop
8 // to demonstrate the use of the dynamic power API.
9 //
10 // The goal is to keep constant the number of elements
11 // that are processed in the vector per millisecond
12 // regardless of the input data
13
14 int main()
15 {
16 const size_t N = 10000000; // Number of elements in the vector
17 const size_t iterations = 10; // Number of times, entire vector operation
will be performed
18 const float min_value = -1024.0, max_value = 1024.0; // Min and Max value for random number
generator
19 const float alpha = 0.2f; // multiplicative factor
20 const int desired_goal = 7800; // desired number of elements to be
processed per millisecond
21
22 std::vector<float> a(N), b(N), c(N);
23 std::random_device random_device;
24 std::mt19937 generator(random_device());
25 std::uniform_real_distribution<> dist(min_value, max_value);
26 auto gen_dist = std::bind(dist, std::ref(generator));
27
28 std::chrono::time_point<std::chrono::system_clock> begin;
29 using float_millisecs = std::chrono::duration<float, std::chrono::milliseconds::period>;
30
31 qspower::init();
32
33 // Set the desired goal of how many elements are to be processed
34 // with tolerance of 100 elements.
35 qspower::set_goal(desired_goal, 100);
36
37 for (size_t j = 0; j < iterations; j++)
38 {
39 begin = std::chrono::system_clock::now();
40
41 // Initialize the source arrays with random numbers
42 std::generate(a.begin(), a.end(), gen_dist);
43 std::generate(b.begin(), b.end(), gen_dist);
44
45 // add both arrays
46 for (size_t i = 0; i < N; i++)
47 {
48 c[i] = sin(alpha * a[i] + b[i]);
49 }
50
51 // measure the time
52 auto measured = float_millisecs(std::chrono::system_clock::now() - begin);
53
54 // feed the SDK runtime with how many elements are processed per millisecond
55 // so it can regulate the cores and frequencies
56 qspower::regulate(N / measured.count());
57 }
58
59 // return the system to the normal power state
60 qspower::clear_goal();
61
62 qspower::terminate();
63
64 return 0;
65 }
第 20 行将所需目标设置为在 1 毫秒内处理 7800 个元素,并使用第 34 行中的 qspower::set_goal(desired_goal) 将其输入 Power Optimization SDK 运行时。作为迭代的一部分,第 36-56 行,程序测量两个参数。 首先,执行向量加法所花费的时间。 其次,使用第一个测量值,N/measured.count() 将计算在 1 毫秒内实际处理了多少个元素。然后使用 qspower::regulate(measured) 将其馈入功率优化 SDK 运行时。 如上所述,使用设定的目标和测量值,Power Optimization SDK 运行时将调整内核的频率以满足所需的目标。
功率模式是排他的。 当应用程序请求一种模式(静态或动态),而另一种功率模式处于活动状态时,新请求将自动取消先前的模式。
注意
仅选定的运行 Android 操作系统的 Qualcomm® 设备支持 Snapdragon™ 功耗优化 SDK。 对于其他设备或操作系统,Power API 可以安全使用,但 Power Optimization SDK 将静默忽略请求并且不会执行任何操作 。