gxm11 / rgmodern Goto Github PK
View Code? Open in Web Editor NEWLicense: zlib License
License: zlib License
【版本】
0.9.0 (commit c16c9ff)
【问题描述】
kernel_ruby.hpp 的 run 函数,在嵌入包模式下,未捕捉内部脚本抛出的异常,导致报错打印非常不可读(似乎会打印某种 dump 格式)。
【期望】
嵌入包模式下,内部脚本抛出异常后,C++ 层打印且只打印异常的 message 和 backtrace。
【版本】
0.9.0 (commit 40ef548)
【问题描述】
rgm::base::timer.tick
函数,使用死循环控帧。此实现会使 CPU 持续空跑,浪费 CPU 资源。
【期望】
实现改为操作系统的信号机制,例如 Windows 上的 WaitableTimer
系列。优先考虑跨平台实现,如果没有方便的跨平台库,则分别为 Windows 与 UNIX 写实现。
现在使用了 SDL_RenderReadPixels 来实现,但是经测试只在 OPENGL 渲染时能正确返回。Direct3d11渲染不能正确返回,有人提过issue并给出了patch(见https://github.com/libsdl-org/SDL/issues/4782),但实测无效。对于d3d11,可能要求开发者:
这些需要等到渲染器可以在运行时选择了再做比较合适。
此时可以顺便考虑引入DX9,相关的shader可以在旧代码里找到,并且很可能get pixel是没问题的。
python代码如下:
import matplotlib.pyplot as plt
from random import random
def target(x):
return x + 0.1 * x - 0.01 * x * x + 0.1 * random() + 0.03
def target2(x):
return x + 0.1 * x - 0.02 * x * x + 0.1 * 0.5 + 0.03
model = [0, 1, 0, 0, 0, 0]
def predict_delay(model, delay):
sum = 0
t = 1
for w in model:
sum += w * t
t = t * delay
return min(delay, max(0, sum))
def train_model(model, delay, real_delay):
lr = 0.01
gamma = 0.001
old_model = [w for w in model]
s = sum([w * w for w in old_model]) - 1
x, y = real_delay, delay
for i, w in enumerate(old_model):
model[i] -= lr * \
(predict_delay(old_model, x) - y) * (x ** i)
model[i] -= lr * gamma * s * w
for i in range(3600):
x = random()
train_model(model, x, target(x))
xs = []
ys = []
ys2 = []
for i in range(100):
x = i / 100
delay = predict_delay(model, x)
real_delay = target(delay)
train_model(model, delay, real_delay)
xs.append(x)
ys.append(target(x))
ys2.append(target2(delay))
plt.figure()
plt.plot(xs, ys, "b*")
plt.plot(xs, ys2, "rx")
plt.plot([0, 1], [0, 1], "k--")
plt.axis([0, 1, 0, 1])
plt.savefig("4.png")
plt.close()
print(model)
其中target是未知的目标函数,输入值是准备传给sleep的delay,输出值是实际的real_delay。target2是无随机扰动的版本。
使用了多项式模型来用real_delay(x)预测delay(y):y = a0 + a1 * x + a2 * x^2 + ... + an * x^n
。模型有初始化的值:除了a1 = 1
,其他系数都为0。模型要求输入值在0~1之间,所以对real_delay要除以当前的帧间隔处理(real_delay不可能大于当前的帧间隔)。
训练的loss函数采用了平方损失函数,并且附带了正则项:((a0^2 + a1^2 + ... + an^2) - 1) ^2
,此项的目的是使所有系数的平方和趋于1。
最后展示的结果是在经过3600次的预训练之后,预测函数的表现。第一张图移除了随机值以便观测。
横坐标是expect_delay,纵坐标是real_delay。蓝色相当于直接sleep(expect_delay),所以real_delay总是大一点;红色相当于sleep(predict(expect_delay)),可见红色已经消除了蓝色的bias,不考虑随机性的情况下,real_delay与expect_delay非常接近。
RT。
AudioContext:对ruby脚本可见的音频上下文对象,一个对象对应一段音频实例,可以通过脚本即时获取该音频相关的信息、状态,以及控制。
提供范例支持不同的分辨率,目前这样设计:
模拟sprite的color效果,方便处理描边等情况。还可以添加tone_mod方法?或者给blt增加混合模式?
在范例中,如果使用控制器,并且打开了输入法测试的箱子,在输入法结束后控制器的按键不可用。重新拔出再插入控制器也会导致控制器按键不可用,看上去重新拔出后控制器的编号变成了1、2而不是始终为0。
RT。因为即使密码错误,RGM::Ext.external_check也会成功
准备参考erlang的设计,使用”Actor“模式,给worker分组,每组在同一个线程执行,组间以协程方式执行。
erlang教程:https://www.tutorialspoint.com/erlang/index.htm
以下几点可能要考虑:
engine包含多个scheduler,每个scheduler在独立的线程里运行。
scheduler在独立线程中执行,它初始化后就会进入主循环。在没有worker的情况下,scheduler不会退出。
分类 | run_in_fiber | 定义run函数 | 调度方式 |
---|---|---|---|
1 | Yes | Yes | 给worker创建新的fiber,执行run函数。 |
2 | Yes | No | 给worker创建新的fiber,执行默认的run函数。此run函数会清空队列,在队列为空或获取数据失败时使用fiber_yield切回到主Fiber。 |
3 | No | Yes | worker的run函数直接阻塞scheduler的运行。这仅适用于scheduler中只有1个worker的情况。 |
4 | No | No | 在主Fiber中,worker会执行默认的run函数。此函数会清空队列,在队列为空或获取数据失败时就会提前结束。 |
worker有自己的可执行任务列表,不在列表中的任务将不会分发给worker。worker有一个队列,其中的任务会从前到后依次执行,队列的实现是std::queue。
worker的运行流程如下,注意,如果worker在fiber中执行,下面的每个都是在切换到fiber后执行的。
当worker获取的share或group数据的owner已经析构时,worker会进入退出状态。
综上,需要实现以下类和函数:
1. engine
- broadcast_task<T_task>(const T_task& t)
- terminate()
2. scheduler
- create_worker<T_worker>()
- remove_worker(size_t worker_id)
- update()
- enqueue_task<T_task>(const T_task& t)
- dequeue_task()
- resume_worker()
- terminated()
3. worker
- lock_data<T_data ...>()
- unlock_data<T_data ...>()
- run_task<T_task>()
- yield()
- setup_owner()
- setup_data()
- bind_data()
- unbind_data()
- terminate()
4. task
- run(T1& t1, T2& t2, ...)
文档:https://speced.github.io/bikeshed
可以使用以下命令将 markdown 文件转换成 html:
%.html : %.md
curl https://api.csswg.org/bikeshed/ -F file=@$< -F force=1 > $@
在VSCode 中使用 live server 插件预览 html 文件。
好奇 如果 ruby 侧通过 Gemfile 引入其他的 gem 脚本,要如何同 RGM 协作?
是否提供对 gemfile 的支持和打包?
调研发现这个库虽然很老但是可以用:https://github.com/paladin-t/fiber
以下代码在windows(msys2 ucrt环境)和linux(Debian GNU/Linux 11 (bullseye))下测试均通过:
#include <cstdio>
#include <vector>
#include "fiber.h"
bool stop = false;
struct worker {
fiber_t* fb_scheduler;
int index;
void run() {
int x = 0;
while (true) {
++x;
printf("worker %d run %d.\n", index, x);
if (x == 5) {
stop = true;
break;
}
yield();
}
yield();
}
void yield() { fiber_switch(fb_scheduler); }
};
std::vector<worker> workers;
struct scheduler {
fiber_t* fb_self;
std::vector<fiber_t*> fibers;
template <size_t id>
static void run(fiber_t*) {
workers[id].run();
}
scheduler() {
workers.resize(3);
fb_self = fiber_create(0, 0, 0, 0);
int index = 0;
for (auto& w : workers) {
w.index = (index++);
w.fb_scheduler = fb_self;
}
fibers.push_back(fiber_create(fb_self, 0, run<0>, 0));
fibers.push_back(fiber_create(fb_self, 0, run<1>, 0));
fibers.push_back(fiber_create(fb_self, 0, run<2>, 0));
}
void run() {
printf("start\n");
for (size_t i = 0; i < 10; ++i) {
if (stop) break;
printf("run %lld\n", i);
for (size_t j = 0; j < fibers.size(); ++j) {
auto fb = fibers[j];
printf("switch to %lld\n", j);
fiber_switch(fb);
printf("switch back\n");
}
}
printf("end\n");
}
};
int main() {
scheduler s;
s.run();
}
// g++ -o main.exe main.cpp
输出:
start
run 0
switch to 0
worker 0 run 1.
switch back
switch to 1
worker 1 run 1.
switch back
switch to 2
worker 2 run 1.
switch back
run 1
switch to 0
worker 0 run 2.
switch back
switch to 1
worker 1 run 2.
switch back
switch to 2
worker 2 run 2.
switch back
run 2
switch to 0
worker 0 run 3.
switch back
switch to 1
worker 1 run 3.
switch back
switch to 2
worker 2 run 3.
switch back
run 3
switch to 0
worker 0 run 4.
switch back
switch to 1
worker 1 run 4.
switch back
switch to 2
worker 2 run 4.
switch back
run 4
switch to 0
worker 0 run 5.
switch back
switch to 1
worker 1 run 5.
switch back
switch to 2
worker 2 run 5.
switch back
end
可见非常完美地实现了协程调度,每次worker调用 yield()
函数时,切换到下一个 worker 执行。由于是单线程模式,被动worker仍然不执行,只有主动worker可以执行,并主动 yield()
放弃执行权。主动 worker 在 flush 前会自动 yield,确保每次以flush开始新的执行。
ruby32分支已创建,这里存一下ruby编译后的二进制文件:
vendors_2.zip
因为github不能上传7z,就用zip包装了一下
opengl下的tilemap存在一定的绘制bug:
目前在测试工程的大地图上发现了这些bug,另外3张小地图没有问题。菜单打开也正常。
经测试bug表现跟tileset有关,可以更换此地图的tileset查看具体效果,尤其是使用第5套海边道路的tileset时,会导致整个画面全部渲染成白色。
目前怀疑是跟自动元件的数量有关,可能tilemap写的部分优化代码有问题,等待进一步排查。
希望给 Bitmap 类提供一个可以画线的方法
报错信息如下:
INFO: RGModern starts running...
WARN: [Kernel] the cooperation type is exclusive.
WARN: [Driver] use direct3d for rendering
WARN: [Driver] max texture 8192 x 8192
start ruby.
resource prefix = resource://
render driver = direct3d9 (2)
build mode = 2
WARN: [Input] text input is stopped
ERROR: Finder cannot find valid path for Data/Scripts.rxdata
ERROR: ERROR: Failed to load embeded script `script/main.rb'.
ERROR: Failed to load embeded script `script/load.rb'.
ruby:in `load_script'
exit ruby.
INFO: RGModern ends with applause.
初步判断是读 Data/Scripts.rxdata 时,Finder出了问题。相关代码如下:
Load_Path[key].each do |directory|
Suffix[key].each do |extname|
path = File.expand_path(filename + extname, directory)
if File.exist?(path)
Cache[filename] = path
return Cache[filename]
end
end
end
可能是expand_path的问题,也可能是 exist? 的问题。
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.