Skip to content
Merged
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
20 changes: 2 additions & 18 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,11 +56,11 @@ FPS comparison of rendering [Franka](https://github.com/Genesis-Embodied-AI/Gene
Resolution: 128x128

<p align="center">
<img src="./scripts/perf_benchmark/example_report/panda_madrona rasterizer_ madrona raytracer_128x128_comparison_table.png" width="600" alt="FPS of gs-madrona rasterizer vs raytracer" align="center"/>
<img src="./docs/perf_franka_128x128_table.png" width="600" alt="FPS of gs-madrona rasterizer vs raytracer" align="center"/>
</p>

<p align="center">
<img src="./scripts/perf_benchmark/example_report/panda_madrona rasterizer_ madrona raytracer_128x128_comparison_plot.png" width="600" alt="FPS of gs-madrona rasterizer vs raytracer" align="center"/>
<img src="./docs/perf_franka_128x128_plot.png" width="600" alt="FPS of gs-madrona rasterizer vs raytracer" align="center"/>
</p>

## Install (Linux Only)
Expand Down Expand Up @@ -104,22 +104,6 @@ renderer = gs.options.renderers.BatchRenderer(
)
```

### Performance Benchmark
For comprehensive performance benchmarking across multiple renderers (Madrona, Omniverse, PyRender, ManiSkill), please refer to the detailed documentation in `scripts/perf_benchmark/README.md`.

The benchmark suite includes:
- Multi-renderer performance testing
- Batch size and resolution scaling tests
- Rasterizer vs raytracer comparisons
- Automated report generation
- Asset preprocessing utilities

Quick start:
```bash
cd scripts/perf_benchmark
python batch_benchmark.py -f benchmark_config_smoke_test.yml
```

## Acknowledgments

The development of gs-madrona is actively supported by [Genesis AI](https://genesis-ai.company/).
Binary file added docs/perf_franka_128x128_plot.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/perf_franka_128x128_table.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
268 changes: 0 additions & 268 deletions include/madrona/context.inl
Original file line number Diff line number Diff line change
Expand Up @@ -112,12 +112,6 @@ inline void Context::iterateQuery(const Query<ComponentTs...> &query, Fn &&fn)
std::forward<Fn>(fn));
}

#ifdef MADRONA_USE_JOB_SYSTEM
JobID Context::currentJobID() const
{
return cur_job_id_;
}
#endif

#ifdef MADRONA_MW_MODE
WorldID Context::worldID() const
Expand All @@ -126,267 +120,5 @@ WorldID Context::worldID() const
}
#endif

#if 0

class Context {
AllocContext mem;

template <typename ArchetypeT>
inline ArchetypeRef<ArchetypeT> archetype();

template <typename ArchetypeT>
inline void clearArchetype();

template <typename ArchetypeT>
inline void clearTemporaries();

template <typename... ComponentTs>
inline Query<ComponentTs...> query();

template <typename... ComponentTs, typename Fn>
inline void forEach(const Query<ComponentTs...> &query, Fn &&fn);

template <typename... ComponentTs>
inline uint32_t numMatches(const Query<ComponentTs...> &query);

// Jobs
template <typename Fn, typename... DepTs>
inline JobID submit(Fn &&fn, bool is_child = true,
DepTs && ... dependencies);

template <typename Fn, typename... DepTs>
inline JobID submitN(Fn &&fn, uint32_t num_invocations,
bool is_child = true,
DepTs && ... dependencies);

// FIXME: currently this function requires that the query reference
// is valid at least until the returned job is completed.
template <typename... ComponentTs, typename Fn, typename... DepTs>
inline JobID parallelFor(const Query<ComponentTs...> &query, Fn &&fn,
bool is_child = true,
DepTs && ... dependencies);

template <typename Fn, typename... DepTs>
inline JobID ioRead(const char *path, Fn &&fn, bool is_child = true,
DepTs && ... dependencies);

#ifdef MADRONA_USE_JOB_SYSTEM
inline JobID currentJobID() const;
#endif

template <typename ContextT, typename Fn, typename... DepTs>
inline JobID submitImpl(Fn &&fn, bool is_child, DepTs && ... dependencies);

template <typename ContextT, typename Fn, typename... DepTs>
inline JobID submitNImpl(Fn &&fn, uint32_t num_invocations, bool is_child,
DepTs && ... dependencies);

template <typename ContextT, typename... ComponentTs, typename Fn,
typename... DepTs>
inline JobID parallelForImpl(const Query<ComponentTs...> &query, Fn &&fn,
bool is_child, DepTs && ... dependencies);

private:
template <typename ContextT, typename Fn, typename... DepTs>
inline JobID submitNImpl(Fn &&fn, uint32_t num_invocations, JobID parent_id,
DepTs && ... dependencies);

#ifdef MADRONA_USE_JOB_SYSTEM
JobManager * const job_mgr_;
StateManager * const state_mgr_;
StateCache * const state_cache_;
IOManager * const io_mgr_;
const int worker_idx_;
JobID cur_job_id_;
#endif

friend class JobManager;
};

template <typename ArchetypeT>
ArchetypeRef<ArchetypeT> Context::archetype()
{
return state_mgr_->archetype<ArchetypeT>(
MADRONA_MW_COND(cur_world_id_));
}

template <typename ArchetypeT>
void Context::clearArchetype()
{
state_mgr_->clear<ArchetypeT>(MADRONA_MW_COND(cur_world_id_,)
*state_cache_, false);
}

template <typename ArchetypeT>
void Context::clearTemporaries()
{
}

template <typename... ComponentTs>
Query<ComponentTs...> Context::query()
{
return state_mgr_->query<ComponentTs...>();
}

template <typename... ComponentTs, typename Fn>
void Context::forEach(const Query<ComponentTs...> &query, Fn &&fn)
{
state_mgr_->iterateQuery(MADRONA_MW_COND(cur_world_id_,) query,
std::forward<Fn>(fn));
}

template <typename... ComponentTs>
uint32_t Context::numMatches(const Query<ComponentTs...> &query)
{
uint32_t num_entities = 0;
state_mgr_->iterateArchetypes(MADRONA_MW_COND(cur_world_id_,) query,
[&](int num_rows, auto ...) {
num_entities += num_rows;
});

return num_entities;
}

template <typename Fn, typename... Deps>
JobID Context::submit(Fn &&fn, bool is_child, Deps && ... dependencies)
{
return submitImpl<Context>(std::forward<Fn>(fn), is_child,
std::forward<Deps>(dependencies)...);
}

template <typename Fn, typename... Deps>
JobID Context::submitN(Fn &&fn, uint32_t num_invocations,
bool is_child, Deps && ... dependencies)
{
return submitNImpl<Context>(std::forward<Fn>(fn), num_invocations,
is_child, std::forward<Deps>(dependencies)...);
}

template <typename... ComponentTs, typename Fn, typename... Deps>
JobID Context::parallelFor(const Query<ComponentTs...> &query, Fn &&fn,
bool is_child, Deps && ... dependencies)
{
return parallelForImpl<Context>(query, std::forward<Fn>(fn), is_child,
std::forward<Deps>(dependencies)...);
}


template <typename Fn, typename... Deps>
inline JobID Context::ioRead(const char *path, Fn &&fn,
bool is_child, Deps && ... dependencies)
{
IOPromise promise = io_mgr_->makePromise();
Job job = makeJob([promise, fn=std::move(fn), io_mgr=io_mgr_](
Context &ctx) {
fn(ctx, io_mgr->getBuffer(promise));
});

io_mgr_->load(promise, path, job);

(void)is_child;
( (void)dependencies, ... );

return JobID::none();
}

// FIXME: implement is_child, dependencies, num_invocations
template <typename ContextT, typename Fn, typename... Deps>
JobID Context::submitImpl(Fn &&fn, bool is_child,
Deps &&... dependencies)
{
JobID parent_id = is_child ? cur_job_id_ : JobID::none();

return job_mgr_->queueJob<ContextT, true>(worker_idx_,
std::forward<Fn>(fn), 0, parent_id,
MADRONA_MW_COND(cur_world_id_, ) JobPriority::Normal,
std::forward<Deps>(dependencies)...);
}

template <typename ContextT, typename Fn, typename... Deps>
JobID Context::submitNImpl(Fn &&fn, uint32_t num_invocations, bool is_child,
Deps && ...dependencies)
{
assert(num_invocations > 0);
JobID parent_id = is_child ? cur_job_id_ : JobID::none();

return submitNImpl<ContextT>(std::forward<Fn>(fn), num_invocations,
parent_id, std::forward<Deps>(dependencies)...);
}

template <typename ContextT, typename... ComponentTs, typename Fn,
typename... Deps>
JobID Context::parallelForImpl(const Query<ComponentTs...> &query, Fn &&fn,
bool is_child, Deps && ... dependencies)
{
if (query.numMatchingArchetypes() == 0) {
return JobID::none();
}

// FIXME: add isRunnable check in addition to no dependencies
if constexpr (sizeof...(dependencies) == 0) {
JobID parent_id = is_child ? cur_job_id_ : JobID::none();

// Additional optimization: skip this proxy ID when only 1 archetype
// is present (in fact for > 1 archetype might make sense to just
// use the else codepath).
JobID proxy_id = job_mgr_->reserveProxyJobID(worker_idx_, parent_id);

state_mgr_->iterateArchetypes(MADRONA_MW_COND(cur_world_id_,)
query, [this, &fn, proxy_id](int num_rows, auto ...ptrs) {
if (num_rows == 0) {
return;
}

// Clang complains this is unused without this->
this->submitNImpl<ContextT>(
[fn = Fn(fn), ptrs...](ContextT &ctx, uint32_t idx) {
fn(ctx, ptrs[idx]...);
}, num_rows, proxy_id);
});

// Note that even though we "relinquish" the id here, it is still safe
// to return the ID, since the generation stored in the ID will simply
// be invalid if the entire parallelFor job finishes, just like a normal
// job id.
job_mgr_->relinquishProxyJobID(worker_idx_, proxy_id);

return proxy_id;
} else {
return submitImpl<ContextT>([fn = std::forward<Fn>(fn), &query] (
ContextT &ctx) {
ctx.state_mgr_->iterateArchetypes(
MADRONA_MW_COND(ctx.cur_world_id_,) query,
[&ctx, &fn](int num_rows, auto ...ptrs) {
if (num_rows == 0) {
return;
}

// FIXME reconsider copying ptrs into the closure here
// FIXME currently copies the user function's closure
// Could allow making a fake jobs with data but not a function
// by extending reserveProxyJobID - that job could be dependent
// on the parallel for job and hold the user function closure.
// If we allowed runtime determined # of dependencies, the
// fast path (no dependencies above) could return the dependent
// data-only job rather than using the fake ID as a parent
ctx.template submitNImpl<ContextT>(
[fn = Fn(fn), ptrs...](ContextT &ctx, uint32_t idx) {
fn(ctx, ptrs[idx]...);
}, num_rows, true);
});
}, is_child, dependencies...);
}
}

template <typename ContextT, typename Fn, typename... Deps>
JobID Context::submitNImpl(Fn &&fn, uint32_t num_invocations, JobID parent_id,
Deps && ...dependencies)
{
return job_mgr_->queueJob<ContextT, false>(worker_idx_,
std::forward<Fn>(fn), num_invocations, parent_id,
MADRONA_MW_COND(cur_world_id_, ) JobPriority::Normal,
std::forward<Deps>(dependencies)...);
}
#endif

}
50 changes: 0 additions & 50 deletions include/madrona/custom_context.inl
Original file line number Diff line number Diff line change
Expand Up @@ -15,55 +15,5 @@ CustomContext<ContextT, DataT>::CustomContext(DataT *world_data,
: Context(world_data, worker_init)
{}

#if 0

template <typename ContextT, typename DataT>
class CustomContext : public Context {
public:
template <typename Fn, typename... Deps>
inline JobID submit(Fn &&fn, bool is_child = true,
Deps && ... dependencies);

template <typename Fn, typename... Deps>
inline JobID submitN(Fn &&fn, uint32_t num_invocations,
bool is_child = true,
Deps && ... dependencies);

template <typename... ComponentTs, typename Fn, typename... Deps>
inline JobID parallelFor(const Query<ComponentTs...> &query, Fn &&fn,
bool is_child = true,
Deps && ... dependencies);
}

template <typename ContextT, typename DataT>
template <typename Fn, typename... Deps>
JobID CustomContext<ContextT, DataT>::submit(Fn &&fn, bool is_child,
Deps && ... dependencies)
{
return submitImpl<ContextT>(std::forward<Fn>(fn), is_child,
std::forward<Deps>(dependencies)...);
}

template <typename ContextT, typename DataT>
template <typename Fn, typename... Deps>
JobID CustomContext<ContextT, DataT>::submitN(Fn &&fn,
uint32_t num_invocations, bool is_child, Deps && ... dependencies)
{
return submitNImpl<ContextT>(
std::forward<Fn>(fn), num_invocations, is_child,
std::forward<Deps>(dependencies)...);
}

template <typename ContextT, typename DataT>
template <typename... ComponentTs, typename Fn, typename... Deps>
JobID CustomContext<ContextT, DataT>::parallelFor(
const Query<ComponentTs...> &query, Fn &&fn, bool is_child,
Deps && ... dependencies)
{
return parallelForImpl<ContextT>(query, std::forward<Fn>(fn), is_child,
std::forward<Deps>(dependencies)...);
}

#endif

}
8 changes: 0 additions & 8 deletions src/core/context.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,6 @@ namespace madrona {

Context::Context(WorldBase *world_data, const WorkerInit &init)
: data_(world_data)
#ifdef MADRONA_USE_JOB_SYSTEM
, job_mgr_(init.jobMgr),
state_mgr_(init.stateMgr),
state_cache_(init.stateCache),
io_mgr_(nullptr),
worker_idx_(init.workerIdx),
cur_job_id_(JobID::none())
#endif
#ifdef MADRONA_USE_TASK_GRAPH
, state_mgr_(init.stateMgr)
, state_cache_(init.stateCache)
Expand Down
Loading
Loading