Large variance in performance of re-trained models.

Hello,
Thank you for your amazing work! SPT's light-weight architecture looks really promising for large remote sensing datasets due to its low latency and memory consumption. However, we're experiencing an issue with a high variance in performance when retraining a model using an identical config. Here's a short background of what we're trying to achieve:
We're currently testing SPT out on our own dataset of infrastructure assets like highway bridges and sign bridges. For this reason we adapted the dales datamodule config  with the two modifications being:

we removed rgb as a feature, since our dataset does not have any color
we removed elevation as a feature, since we encountered similar problems, such as the ones described in issue #32. The relative elevation of points would be important, but the dataset would require us to manually clean up bridge reflections on the road, which end up being single points ~7m bellow the lowest road surface in the point cloud. For now, this is a quick solution we chose.
the resulting datamodule config can be found here: snrwl-template_v1-00_voxel-variant_00.yaml (and corresponding experiment config)

Out of the box our results were slightly worse than other architectures, which SPT should outperform on benchmark datasets. With the current configuration we can achieve a validation mIoU of :

Architecture
mIoU

PointNext-XL
71.67

KPConv
70.77

PTv3
76.11

SPT
70.38

So far this is good but it has led us to suspect that there is potentially some more hyperparamter tuning we can do to improve our results further. However, the problem is that even retraining the model with the same configuration leads to vastly different results, preventing us from attributing one hyperparameter change to a specific improvement. For example, the following is a list of sorted mIoU results we achieve in 13 runs with the config mentioned above (mIoU standard deviation of ~1.26 and a range of ca. 5%):
In [3]: mious
Out[3]:
array([70.38345337, 69.77773285, 69.54872131, 68.86537933, 68.28470612,
       68.27809143, 68.10830688, 67.68677521, 67.30361176, 67.17458344,
       66.95844269, 66.50408173, 65.95107269])

In [4]: mious.mean()
Out[4]: 68.06345837

In [5]: mious.std()
Out[5]: 1.2676893110159888

In [6]: print(mious.min(), mious.max())
65.95107269 70.38345337

The values are reported at the end of training or by using the src/eval.py script. There doesn't seem to be a large difference if we re-eavluate the same model twice.
Can you suggest how we can reach a point where the mIoU is stable between training runs? Or is this the expected behavior? If so, what could be the reason for this?
Thank you in advance

Hello @loicland,
Thanks for the quick suggestions. I believe this has helped me to pinpoint what the issue could be. The variance is observed only on the validation data ( the training performance is overall constant throughout runs), so it could be that there is some overfitting happening on ambiguous classes.
Our dataset is indeed challenging with large differences in object sizes and total number of points. The size of the dataset could be considered moderate with a split of 48 training point clouds and 21 validation examples. Here's a screenshot of the distribution:
| # | Class | Number of points | Number of objects |

And here's I think the main limitation of our dataset - some point clouds were labeled before an additional feature 'intensity' was removed (since not all point clouds had it), leading to one of the classes (the side lane of the road) being ambiguous based on geometric features alone. This causes superpoints to bleed out into the actual road, which also shows in large variance in the class 'IfcRoad_roadside'.

ground truth
prediction
errors

partition level 1
partition level 2
partition level 3

Since posting the issue I pinned some hyperparameters on their highest mIoU respectively, which actually reduced the variance somewhat. Interestingly node_feat_jitter 0. --> 0.01 and h_edge_feat_jitter 0. --> 0.03 had the highest positive effect.
I still need to play around with the values more but for now this is what I am getting with 5 runs/value:
pcp_regularization: [0.1, 0.2, 0.3] 	-->	 70.078 mIoU (+/-0.683); max mIoU = 71.244
pcp_regularization: [0.1, 0.5, 1.5] 	-->	 70.307 mIoU (+/-0.582); max mIoU = 71.127
pcp_regularization: [0.05, 0.1, 0.2] 	-->	 69.900 mIoU (+/-0.725); max mIoU = 71.273
pcp_regularization: [0.2, 0.8, 2.0] 	-->	 70.156 mIoU (+/-0.626); max mIoU = 70.972

I consider this issue solved since the variance is now notably lower.
But I would still like to ask you - regarding pcp_regularization and the corasness of the graph: Does it in any way affect the receptive field of the network,e.g. fine superpoints = small receptive field? Or is the receptive field global - e.g. each superpoint at $\mathcal{P}_1$ attends to all other superpoints at the same level regardless of how many superpoints there are? Eq. (3) from your paper would suggest that self-attention is applied on the immidiate neighbours in the graph only (but perhaps my understanding is wrong)?

Hi @biophase, thank you for the detailed feedback !
Class imbalance
Indeed, heavy class imbalance will affect generalization performance and introduce variance in the results since a small change of prediction on a rare class may have a dramatic impact in the metrics. This is not specific to SPT, but the superpoint partition might exacerbate this behavior for classes of small, under-represented objects (eg bridge pier, bride railing, footing, traffic sign, ...).
Radiometric features
As you identified, radiometric information can be crucial to separate some classes that would otherwise not be distinguishable based on geomeetry alone. Again, this is not a SPT-specific problem, any 3D processing method would struggle identifying a poster in a wall (or lane on the road) based on geometry alone.
Depending on the ratio of your points having an intensity (and whether you expect to have access to in your typical inference scenario), it may be worth using it anyways and setting it to 0 when not available. You can see the DALES dataset implementation for how to use intensity. Also, you can play with node_feat_drop and node_feat_jitter in your datamodule config to introduce some augmentations on the point features and see if that helps.
Augmentations
Indeed node_feat_jitter and h_edge_feat_jitter are augmentations that may be worth exploring for your own dataset. You can tune many different augmentations in datamodule configs:
# Augmentations parameterization
pos_jitter: 0.05
tilt_n_rotate_phi: 0.1
tilt_n_rotate_theta: 180
anisotropic_scaling: 0.2
node_feat_jitter: 0
h_edge_feat_jitter: 0
v_edge_feat_jitter: 0
node_feat_drop: 0
h_edge_feat_drop: 0.3
v_edge_feat_drop: 0
node_row_drop: 0
h_edge_row_drop: 0
v_edge_row_drop: 0
drop_to_mean: False

but also for batch construction:
# Batch construction parameterization
sample_segment_ratio: 0.2
sample_segment_by_size: True
sample_segment_by_class: False
sample_point_min: 32
sample_point_max: 128
sample_graph_r: 50  # set to r<=0 to skip SampleRadiusSubgraphs
sample_graph_k: 4
sample_graph_disjoint: True
sample_edge_n_min: -1  # [5, 5, 15]
sample_edge_n_max: -1  # [10, 15, 25]

sample_segment_ratio, sample_graph_r, sample_graph_k, might have an impact on performance (but also on GPU memory). sample_segment_by_class might also be worth a try for your class imbalance problem.
Receptive field
Each superpoint attends to neighboring superpoints in the same partition level. The neighborhood is constructed at preprocessing time with RadiusHorizontalGraph. You can play with graph_gap in your datamodule config, this rules the minimum pointwise distance for two superpoints to be neighbors (radius NN search but for point sets, described in our paper's appendix). Be aware that increasing the number of neighbors of a superpoint will increase the number of edges in the attention graph, which may in turn impact compute and memory. graph_k_max can help you keep the number of edges per superpoint in check. Also, max_num_nodes and max_num_edges can be adjusted if need be.


Skip 0 byte writes

Fixes #2249

There are no tests on this file... so I'm not sure where to go on this.
Theoretically, one could be written, but that would take me a long time.

LGTM - but first, change the description to say "Fixes #2249".

(Usual disclaimer - wait until tests pass "sufficiently" before merging)


Asynchronous Validation in 2.20.2 don't work

Hi,
It seems that there's something wrong with the use of bluebird in 2.20.2.
app.use(expressValidator({
  customValidators: {
    isUsernameAvailable: function(username) {
      return new Promise(function(resolve, reject) {
        resolve(true)
      });
    }
  }
}));

And got the message TypeError: promise.reflect is not a function in console
I downgraded to 2.20.1 and it works.

Weird. When you do npm install, does it install bluebird 3.3.x as one of our dependencies? All of our tests pass relating to async errors, so that's the only thing I can think of...

Yes 3.3.4. Maybe i'm doing something wrong.
I reproduce it with a simple case. Express init, add in package json "express-validator": "2.20.2"
app.js
var bodyParser = require('body-parser');
var express = require('express');
var expressValidator = require('express-validator');
var path = require('path');

var app = express();

app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: true}));
app.use(
    expressValidator(
        {
            customValidators: {
                testAsync: function (param) {
                    return new Promise(
                        function (resolve, reject) {
                            resolve();
                        }
                    );
                }
            }
        }
    )
);

app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');

app.get(
    '/test',
    function (req, res) {
        res.render('index');
    }
);

app.post(
    '/test',
    function (req, res) {
        req.checkBody('param', 'param ko').testAsync();

        req.asyncValidationErrors()
            .then(
                function () {
                    res.send('ok');
                }
            )
            .catch(
                function (errors) {
                    console.log('catch');
                    console.log(errors);
                    res.send(errors);
                }
            )
        ;
    }
);

module.exports = app;

And in console, after submit the form :
catch
[TypeError: promise.reflect is not a function]

@AuspeXeu can you look into this since you made those changes? If not, I won't be able to look into this until Monday.

Sorry, I am super busy myself.

@poupou-keud Are you using the native Node promises or Bluebird promises? If the former, I think that is where the issue may be. Our dummy app in our tests assume that users are passing us a Bluebird promise (https://github.com/ctavan/express-validator/blob/master/test/helpers/app.js#L5). We probably need to be converting promises to Bluebird promises in express-validator.js so that promise.reflect() is a valid function.

Works fine in 2.20.3
Thx


Balance returns 0 after any wallet transaction

As per latest changes, the following rule was implemented:
Remove inputs from the db, to prevent accidental double-spend attempts when sending transactions quickly after one another.

As a side effect, balance command will always return 0 until next block is accepted.  Would we need to document this or handle it in another way? @julesdesmit
> loadwallet password
Wallet created successfully!
Public Address: 2AabBNzuaTiF8wJ5KWSwLXY5wffH32LPEvJAZehw1g6WKqtTYgJxuvTo8FVjUD5UEoQRhBEtibfD1cMESFXXKAgCeXhGMh
> balance
25000000
> transfer 1234 2eMD4b8B1id1Xkt3ngttfYG2ESuP2UAarPDVF3URMtscZdmtvEjUdWU5GqmzqxfDanuNQcDvgeaE421HP5b912FMeRapXh
Txn Hash: 5ebdaa916d048187414cd9f318194a40b42cf59067031c514df731e05787a0a9
> balance
0

Good catch. I wonder if there would be an easy way to have something like
> balance
0 (25000000 pending)

or something similar.

Indeed, currently a similar approach is being implemented where value tagged as pending would show the wallet outputs total balance from mempool (unconfirmed) txs
Another note worth mentioning is that the balance might be constantly printed as 0 as we've got sendBid/sendStake automated by StakeAutomation.

Another note worth mentioning is that the balance might be constantly printed as 0 as we've got sendBid/sendStake automated by StakeAutomation.

In a default configured case, the StakeAutomaton only sends a stake and bid once every 249900 blocks (if I remember the default offset being 100 correctly).

Makes sense. I'll double check.
Meanwhile, let me know if the scenario below works for us (it's already implemented)
Before sending transfer tx

balance
Balance 1000.00000000, Unlocked Balance 1000.00000000
transfer 0.00000200 2eMD4b8B1id1Xk...
Txn Hash: 6cde7ee0292897...

After sending transfer tx
Unlocked Balance shows the unspent wallet amount
Balance shows the sum of both wallet amount and pending to be received

balance
Balance<PHONE_NUMBER>0, Unlocked Balance 0.00000000

After tx is accepted

balance
Balance<PHONE_NUMBER>0, Unlocked Balance<PHONE_NUMBER>0

Yes this is fine! Feel free to open a PR for it.


Using cluster commands in failover mode (sentinel)

I have 3 x caddy instances with 3 x redis/redis-sentinel instances, but it looks like redis does not support some of the commands caddy-storage-redis is sending:
Nov 27 05:34:59 lb1 caddy[92912]: Error: loading initial config: loading new config: loading storage module: loading module 'redis': provision caddy.storage.redis: ERR unknown command 'cluster', with args beginning with: 'slots'

I have TLS storage configured as below, does it somehow still require redis in cluster mode?
{
    storage redis failover {
        address {
        <IP_ADDRESS>:26379
        <IP_ADDRESS>:26379
        <IP_ADDRESS>:26379
        }

        prefix "caddy"
        password "SECRET"

        tls_enabled false
        tls_insecure false
        compression false
    }
}

OK looks like I get similar error when using CLI to connect to redis sentinel directly:
<IP_ADDRESS>:26379> CLUSTER SLOTS
(error) ERR unknown command 'CLUSTER', with args beginning with: 'SLOTS'
<IP_ADDRESS>:26379> CLUSTER SHARDS
(error) ERR unknown command 'CLUSTER', with args beginning with: 'SHARDS'

When connecting to redis directly from CLI:
<IP_ADDRESS>:6379> CLUSTER SLOTS
(error) ERR This instance has cluster support disabled
<IP_ADDRESS>:6379> CLUSTER SHARDS
(error) ERR This instance has cluster support disabled

I am not certain but I am guessing the CLUSTER commands are specifically for Redis Cluster product?


Recersive option

Any chance we could get a recursive option to go through sub-folders?

This should be doable, but it might have to wait until the script uses file names for parsing. The current subsequent file matching might cause a conflict with nested directories.

This is probably implemented now, but I haven't tested it. I will close this issue until someone discovers that it doesn't work.


Inactive Functions and Permissions are not visible in the graphcool.yml

We do not print out inactive Functions and PermissionQueries to the graphcool.yml at the moment. This can lead to confusion if the user later on tries to create a Function with the same name or in the case of a RP function tries to create one for the same model, binding and operation and gets an error that the local yml will not give him any clue about.

As a workaround we should print but comment-out disabled functions/permissions while "ejecting" them from the legacy state.

Commenting out is a rather awkward way to deal with this. At first sight, it makes sense to add commented-out entries for disabled functions/permissions, but would a new deploy not complete remove them then?
The enabled option was removed from the graphcool.yml because support for it would end, but it seems that for the transition phase the only way to not risk loosing anything is by re-adding support for enabled:true on functions and permissions again.

Commenting out and deploying will remove the disabled function/permission from the project. This is no "functional" change, as they were disabled before.
All functions and permission queries are still persisted on the file system. The only thing getting lost is disabled permissions without a permission query.
I think this is a fair trade-off.

I like the enabled/disabled flag on functions, because you can't conditionally comment something, but you can use an environment variable to enable a stub function on dev, while actually connecting to a third party in production. However, this is a different use case, that's unrelated to this.

When a function is disabled in UI and I try to run deploy, I get an error message Function with name 'DisabledFunction' has invalid payloadName: 'SomePayload'. It's really confusing, especially since it talks about a function I haven't even modified :)
Reading discussion here, I'll add my two cents. What's the purpose of disabling a function with a new framework? With the legacy approach, I've used it once mostly just to mark the function that is broken. I cannot think of use case where you would disable a function that is actually used somewhere and causing unhandled errors because of that.
If you want to keep this feature, I think it should be just ignored by a new framework. Meaning when you deploy, the function code is updated, but its enabled status is kept. Although then we are getting back to the topic of use case and why would you update code for something that you don't want to use. CLI would probably need to warn about it.
Another option is to have disabled flag directly in graphcool.yml so instead of commenting out whole function block, you would just add this flag and deploy. Suddenly it's not just some transient state that you can control with web interface only, but it's also part of version control.

@FredyC That's what I meant with 'liking the enabled/disabled flag of functions', in the project file. It used to be in one of the earliest versions of the CLI beta. I already described one use case for it, which is enabling/disabling function versions specific to an environment. Having a logging function enabled only in dev/test for example, or a stub function for an external system that is not available in dev.
I think it shouldn't be a part of the console at all. Actually, I believe in a headless system, and I don't believe that any of the features related to functions should be a part of the console anymore.

Well, your use case still does not make much sense. Imagine that your app would be calling that logging function. Suddenly you disable it and those requests start to fail. Why not disable logging in the code of your app instead of sending useless requests in a production app?

In my opinion list of functions in Console should be used purely for advanced display of logs only. I would not remove it completely. CLI is kinda limited for visual interactions.

@FredyC You are just thinking about resolver functions. Disabling those would break client apps. However, there are also operation hooks, and subscription functions. And even for resolver functions, disabling one, and enabling another, based on environment, also does not break client apps.


Webhook for Transactions (Jobs) Status

Wondering if there is a plan to add some kind of webhook functionality so that the interested parties can be updated for the status of transactions (jobs) or account creation status, instead of needing to poll the related HTTP API endpoints.

There's no timeline for this feature yet unfortunately. See related discussions in #155 :)

We are thinking about adding a webhook support for job status updates. This webhook would be configurable via env vars (as everything else) and would receive a POST request on job status updates.

@latenssi , glad to hear this, thank you for planning to add this feature.
The requirement you've mentioned above seems to be perfect already.
One thing I'd like to add is to have some kind of retry mechanism with exponential backoff when the webhook was failed to be delivered (not getting back 2xx http status code as a response).

@SiriusDely Thank you for the feedback!
We will use the existing job scheduling infra for sending the notifications. This means if a webhook fails (error or status code != 200) the scheduler will try again in exactly 1 minute and retry a maximum of 10 times. I understand this is not ideal in a web environment but we don't want to implement a second scheduler just for webhooks. It would be ideal to have the job scheduler doing the exponential backoff some day so all the async jobs benefit from it.

sounds great @latenssi !


Parse Server doesn't start with LiveQuery on Azure

Hello,
I would like to try LiveQuery. I update package.json with :
{
  "name": "parse-server-example",
  "version": "1.0.0",
  "description": "An example Parse API server using the parse-server module",
  "main": "index.js",
  "repository": {
    "type": "git",
    "url": "https://github.com/Azure/parse-server-example"
  },
  "license": "MIT",
  "dependencies": {
    "express": "~4.2.x",
    "kerberos": "~0.0.x",
    "parse": "^1.8.0",
    "parse-server": "~2.2.6",
    "parse-server-push-adapter": "^1.0.0"
  },
  "scripts": {
    "start": "node index.js"
  },
  "engines": {
    "node": ">=4.3"
  }
}

If I add these lines :
// Initialize a LiveQuery server instance, app is the express app of your Parse Server
var httpServer = require('http').createServer(app);
httpServer.listen(port);
var parseLiveQueryServer = ParseServer.createLiveQueryServer(httpServer);

Do I need add some other variable ??

see this manual : https://github.com/ParsePlatform/parse-server/wiki/Parse-LiveQuery

I read it. but it can't help me about my configuration.
I have all information required.

httpServer.listen(port);
this line create a trouble on my server.

What's your error?

I need to do some tests, but I may resolve it :
I delete this code :
app.listen(port, function() {
    console.log('parse-server-example running on port ' + port + '.');
});

and replace with this code :
var port = process.env.PORT || 1337;
var httpServer = require('http').createServer(app);

httpServer.listen(port, function() {
    console.log('parse-server-example running on port ' + port + '.');
});

Parse is running.

You're listening 2 times on the same port I belive...

right. the document don't ask to modify the port. Must I do it ?

I'm not sure. What's the error that you have??

The logstream tell me nothing.
If I stop app.listen, parse server doesn’t work ?
Thank you

Le 8 avr. 2016 à 15:59, Florent Vilmart<EMAIL_ADDRESS>a écrit :
I'm not sure. What's the error that you have??
—
You are receiving this because you authored the thread.
Reply to this email directly or view it on GitHub https://github.com/ParsePlatform/parse-server/issues/1426#issuecomment-207443043

@Sofianebenabdallah
remove app.listen() and add the LiveQuery configuration code.
// Initialize a LiveQuery server instance, app is the express app of your Parse Server
var httpServer = require('http').createServer(app);
httpServer.listen(1337);
var parseLiveQueryServer = ParseServer.createLiveQueryServer(httpServer);

Following is the complete setup of Parse-Server with LiveQuery in same process. Feel free to copy-paste.
var express = require('express');
var ParseServer = require('parse-server').ParseServer;
var app = express();

var api = new ParseServer({
  databaseURI: 'mongodb://localhost:27017/parse', // Connection string for your MongoDB database
  cloud: '/home/username/project/cloud/main.js', // Absolute path to your Cloud Code
  appId: 'appId',
  masterKey: 'masterKey', // Keep this key secret!
  fileKey: 'optionalFileKey',
  serverURL: 'http://localhost:1337/parse', // Don't forget to change to https if needed
  liveQuery: {
    classNames: ['Test', 'TestAgain']
  }
});

// Serve the Parse API on the /parse URL prefix
app.use('/parse', api);

// app.listen(1337, function() {
//   console.log('parse-server-example running on port 1337.');
// });

// Initialize a LiveQuery server instance, app is the express app of your Parse Server
var httpServer = require('http').createServer(app);
httpServer.listen(1337);
var parseLiveQueryServer = ParseServer.createLiveQueryServer(httpServer);


RuntimeError: Optimizer config for 'xyz' not found in config file.

I have resolved this issue with your guidance, #(https://github.com/WU-CVGL/BAD-Gaussians/issues/5) but encountered a new problem when running the code.
I run the code ns-train bad-gaussians --data /path/my/data/  --pipeline.model.camera-optimizer.mode "cubic"  --vis viewer+tensorboard nerfstudio-data  --eval_mode "all" --downscale_factor 4
and the bug is:
RuntimeError: Optimizer config for 'xyz' not found in config file. Make sure you specify an optimizer for each parameter group. Provided configs were: dict_keys(['means', 'features_dc', 'features_rest', 'opacities', 'scales', 'quats', 'camera_opt'])
Did my training fail?
then I run the code : [ns-viewer --load-config /path/outputs/data/config.yml. the bug is
───────────────────────────────────────────────────────
Error
No checkpoint directory found at outputs/blurtanabata/data/nerfstudio_models,
Please make sure the checkpoint exists, they should be generated periodically during training
"Did I miss a step? Why are there no checkpoints?"

Hi, the training is failed indeed. In a previous issue (#2), I upgraded the parameter names in BAD-Gaussians following the nerfstudio upstream (https://github.com/nerfstudio-project/nerfstudio/pull/2946/files), so you need to install the latest nerfstudio:
(FYI, recently I updated the docs with nerfstudio installation here)
# install nerfstudio!
git clone https://github.com/nerfstudio-project/nerfstudio
cd nerfstudio
pip install --upgrade pip setuptools
pip install -e .

and this may overwrite the gsplat (in issue #2), thus we also reinstall it:
# make sure old version is uninstalled
pip uninstall gsplat
# install the forked version with camera pose gradient enabled
pip install git+https://github.com/LingzheZhao/gsplat

sorry. My nerfstudio environment has been stuck in the failed compilation of tinycudann.  So I haven't had a chance to go through the entire process again.

sorry. My nerfstudio environment has been stuck in the failed compilation of tinycudann. So I haven't had a chance to go through the entire process again.

Oops. Actually you can skip installing tinycudann since it is not necessary for 3D-GS. However there must be something wrong with the environment. I suggest creating a new conda environment and everything should be okay.

Sorry, I was busy with other projects recently. I followed your tutorial and succeeded, although I encountered a problem with mismatched gcc versions in the middle, which I have resolved. However, now I am encountering an error when executing
pip install git+https://github.com/LingzheZhao/gsplat
the error is :

is this a mismatched CUDA version issue ?

Thank you for your continuous interest in our work!
Assume that you have installed the cuda toolkit 11.8 in a fresh conda environment badgaussian with conda install -c "nvidia/label/cuda-11.8.0" cuda-toolkit as described above. Can you try the following:
export CUDA_HOME="/home/<YourUserName>/miniconda3/envs/badgaussian/"
pip install git+https://github.com/LingzheZhao/gsplat

If this works, then you can make this permanent in this conda environment with:
conda env config vars set CUDA_HOME="/home/<YourUserName>/miniconda3/envs/badgaussian/"

sorry.  I run the
pip install git+https://github.com/LingzheZhao/gsplat
the error is :

The installation process of gsplat always fails.

Hi, it seems that the setuptools failed to detect the architecture of your GPU, thus the arch_list is empty. You can try setting this environment variable before pip install:
export TORCH_CUDA_ARCH_LIST="7.0;7.2;8.0;8.6;8.9"

If this does not work, note that the official gsplat also supports pose optimization now, and you can also try that (pip install -U gsplat). After installation, it will build the CUDA code on the first run (JIT).

Thanks a lot. I have resolved the issue with the environment configuration, which was caused by the installation of  tiny-cuda-nn


Image Stylization should make use of GPU, and optionally take advantage of CUDA too

I really appreciate the work you guys have done on magenta here in including image stylization, which I am passionately interested in and would love to use cloudML to do some stuff in the future with it since this is already using TensorFlow.
However this project https://github.com/jcjohnson/fast-neural-style is a lot faster for me using cutorch/cudnn taking advantage of my nvidia gpu.
If we could have parity over here I think that would be ideal!

The current model wasn't well optimized for speed. We agree that it's too
slow.
Do you have some benchmark results? I'd love to see how we're doing.
On Fri, Nov 11, 2016 at 9:25 AM Kevin LaMar<EMAIL_ADDRESS>wrote:

I really appreciate the work you guys have done on magenta here in
including image stylization, which I am passionately interested in and
would love to use cloudML to do some stuff in the future with it since this
is already using TensorFlow.
However this project https://github.com/jcjohnson/fast-neural-style is a
lot faster for me using cutorch taking advantage of my nvidia gpu.
If we could have parity over here I think that would be ideal!
—
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
https://github.com/tensorflow/magenta/issues/379, or mute the thread
https://github.com/notifications/unsubscribe-auth/APkejNzKCN6qUcHnJbasLVg172BRfLaGks5q9KT7gaJpZM4Kv9jb
.

I'll try to get you some benchmarks next week as I am at a conference this week.

where is the code/example that is being referenced here ?

for the use of gpu :
you can replace code in the image_stylization_transform.py :
with tf.Graph().as_default(), tf.Session() as sess:

(line 86 and line 105) by
device_t='/gpu:0'
g = tf.Graph()
soft_config = tf.ConfigProto(allow_soft_placement=True)
soft_config.gpu_options.allow_growth = True
with g.as_default(), g.device(device_t), \
        tf.Session(config=soft_config) as sess:

If it does not work, that's probably because you are using annaconda and the tensorflow version installed by default in the environment magenta  does not support GPU.
In this case, you need to reinstall tensorflow (make sure that cuda, cudnn are already well installed.)
enter the environment magenta by
source activate magenta
and then
pip uninstall tensorflow
if python 2.7 :
pip install --ignore-installed --upgrade https://storage.googleapis.com/tensorflow/linu/gpu/tensorflow_gpu-1.0.1-cp27-none-linux_x86_64.whl
if python 3.x :
please check https://www.tensorflow.org/install/install_linux#installing_with_anaconda for installing tensorflow with GPU support.
it works for me :

name: GeForce GTX 1080

major: 6 minor: 1 memoryClockRate (GHz) 1.7335

pciBusID 0000:03:00.0

Total memory: 7.92GiB

Free memory: 7.62GiB

I tensorflow/core/common_runtime/gpu/gpu_device.cc:906] DMA: 0

I tensorflow/core/common_runtime/gpu/gpu_device.cc:916] 0:   Y

I tensorflow/core/common_runtime/gpu/gpu_device.cc:975] Creating TensorFlow device (/gpu:0) -> (device: 0, name: GeForce GTX 1080, pci bus id: 0000:03:00.0)

hope that will help.


dotnet run

Problem encountered on https://dotnet.microsoft.com/en-us/learn/dotnet/hello-world-tutorial/run
Operating System: windows
Provide details about the problem you're experiencing. Include your operating system version, exact error message, code sample, and anything else that is relevant.
C:\Users\franc\MyApp\Program.cs(2,1): error CS8802: Only one compilation unit can have top-level statements. [C:\Users\franc\M
yApp\MyApp.csproj]
The build failed. Fix the build errors and run again.

My apologies for not responding on time...  your answered made sense after
confirming what the issue was. THANK YOU SO MUCH.
On Fri, Jun 9, 2023, 12:11 github-actions[bot] @.***>
wrote:

This issue is stale because there has been no response to a request for
more information for 7 days.
—
Reply to this email directly, view it on GitHub
https://github.com/dotnet/core/issues/8514#issuecomment-1584902408, or
unsubscribe
https://github.com/notifications/unsubscribe-auth/AOKMBUELGLR2XEDNOB36Q63XKNKL3ANCNFSM6AAAAAAYYRRSLY
.
You are receiving this because you were mentioned.Message ID:
@.***>

You're welcome. It seems your issue is solved, so I'm closing this.


fix: reactPlugin skip inject react hmr code to workerFile (fix #6148)

Description

Additional context

What is the purpose of this pull request?

[x] Bug fix
[ ] New Feature
[ ] Documentation update
[ ] Other

Before submitting the PR, please make sure you do the following

[x] Read the Contributing Guidelines.
[x] Read the Pull Request Guidelines and follow the Commit Convention.
[x] Check that there isn't already a PR that solves the problem the same way to avoid creating a duplicate.
[x] Provide a description in this PR that addresses what the PR is solving, or reference the issue that it solves (e.g. fixes #123).
[ ] Ideally, include relevant tests that fail without this PR but pass with it.

in vite-react project, when import a worker which contains 'react' word and export function name's FirstLetter is capital, the react/plugin will inject the hmr code to the worker.
reproduction : issue #6148  's repo.
// worker.js
// react
export function Thing() { return 1 }

in packages\plugin-react\src\index.ts file

check the 'react' keyword
inside the isRefreshBoundary fn will check the worker's export function name whether isComponentLikeName

before

after add the isWorker check

i compare the webpack version(create-react-app) and vite:
in webpack , the react-refresh-webpack-plugin will generate each JS-LIKE module
https://github.com/pmmmwh/react-refresh-webpack-plugin/blob/main/loader/utils/getRefreshModuleRuntime.js
but vite will transform if it's isJSX or code includes 'react' https://github.com/vitejs/vite/blob/d8502e24cf971f6c7f1801c9db16fe34cf4cd6ea/packages/plugin-react/src/index.ts#L121
the util.js transformed result by webpack/vite (simplified version):
// util.js with 'react' keyword
export function Test() {
  console.log("Capital fn");
}
export function normal() {
  console.log("normal"); // react words here
}

// transform by webpack
function Test() {
  console.log("Capital fn");
}
_c = Test;
function normal() {
  console.log("normal"); // react words here
}
var _c;
// 1. regist
__webpack_require__.$Refresh$.register(_c, "Test");
// 2. react refresh
$ReactRefreshModuleRuntime$($ReactRefreshCurrentExports$);

// transform by vite
if (import.meta.hot) {
  window.$RefreshSig$ = RefreshRuntime.createSignatureFunctionForTransform;
}
export function Test() {
  console.log("Capital fn");
}
_c = Test;
export function normal() {
  console.log("normal"); // react words here
}
var _c;
// 1. regist
$RefreshReg$(_c, "Test");
if (import.meta.hot) {
  // 2. react refresh
  RefreshRuntime.performReactRefresh();
}

but if there are no 'react' in util.js, vite wouldn't transform the file.
maybe because it is difficult to know exactly whether a component is a react component, so react-refresh-webpack-plugin just transform each  JS-LIKE module(and webpack can config worker-loader which won't insert refresh code into workerFile to handle worker import).
so i think maybe we could do the same , inject hmr to each JS-LIKE module, but ignore the workerFile.
like this:
let useFastRefresh = false
if (!skipFastRefresh && !ssr && !isNodeModules) {
  // Modules with .js or .ts extension must import React.
  // const isReactModule = isJSX || code.includes('react')
  // if (isReactModule && filter(id)) {
  // ---Replace isReactModule with isWorker condition here---
  if (!isWorker && filter(id)) {
    useFastRefresh = true
    plugins.push([
      await loadPlugin('react-refresh/babel.js'),
      { skipEnvCheck: true }
    ])
  }
}

@aleclarson  what do you think ? 😅

Vite requires .js modules to import React explicitly. We don't want to change that
Could you update the code.includes("react") check to use importReactRE.test?
https://github.com/vitejs/vite/blob/2825779b435deda15008ca546023f2ca65723e01/packages/plugin-react/src/index.ts#L65


Automatically Set Layout Part To Inline Edit For Content Editors

Is there a way to set the Layout Part to Inline edit and remove the elements section for Content Editors other than maybe modifying it myself?

Not currently. This could become a setting on the Content Type/Part edit screen though.


fix(#patch); rari-vaults; addressing QA

Fixing #448
Changes:

Added context to README.md
Using TVL for outputTokenPriceUSD to stay consistent
Add notes to readme about vault tvl including "unclaimed fees"
update to version 1.4.1

Testing: https://okgraph.xyz/?q=dmelotik%2Frari-vaults

Nice work!


Fix: Hide config.SecretURL when the URL is incorrect.

Issue
Fixes https://github.com/prometheus/alertmanager/issues/3884
Changes Made
Updated the config.go to redact the URL.
Added test cases to check URL stays hidden.
Testing Performed

[x] Unit Tests
[x] Manual tested sending a mal-formatted url.

Thanks!


Update composer.json

Your requirements could not be resolved to an installable set of packages.

  Problem 1
    - Installation request for dektrium/yii2-rbac dev-master -> satisfiable by dektrium/yii2-rbac[dev-master].
    - dektrium/yii2-rbac dev-master requires kartik-v/yii2-widget-select2 2.0.* -> no matching package found.

Potential causes:
 - A typo in the package name
 - The package is not available in a stable-enough version according to your minimum-stability setting
   see <https://groups.google.com/d/topic/composer-dev/_g3ASeIFlrc/discussion> for more details.

Read <https://getcomposer.org/doc/articles/troubleshooting.md> for further common problems.

@dmeroff this is urgent

@thiagotalma I cannot reproduce the issue. What is your minimum-stability setting in your composer.json?

"minimum-stability": "dev",

It's weird. I still cannot reproduce. Anyway, I'm merging your PR because it really does not matter which version to use.

Thanks!!!


Select which camera to initially show

The back camera is always initial selected by default in the via controller. After the view controller is shown the can toggle between the front and back camera.
Would it be possible to choose which camera is selected by default?

For the moment this is not possible. Its Swift counterpart already supports this feature but I don't have enough time to support them both.
If you want add this feature, don't hesitate.

You can call [_codeReader switchDeviceInput] at viewDidLoad.... It have worked great for me...


Matrix transform error when displaying TabBar

Tested versions
v4.3.dev.custom_build [c8c483cf5]
System information
Windows 11 Lenovo laptop
Issue description
I was getting this problem when developing an addon, but then realized it was being caused by the Godot editor itself as well.  Basically whenever a TabBar is first shown, either when first added to a tree or when the user foregrounds the Godot application, this error occurrs.  It's caused by Transform2D.affine_inverse failing due to a 0 determinant.
Steps to reproduce
Compile Godot in Visual Studio and place a breakpoint at /core/math/transform_2d.cpp line 51.  Run Godot with debugging enabled.  Before the project select screen even shows, the debugger will halt on this line.  The breakpoint will also be hit if you switch to another window and then switch back.
Minimal reproduction project (MRP)
Just compile and run Godot v4.3.dev.custom_build [c8c483cf5] with debugging enabled and a breakpoint at /core/math/transform_2d.cpp line 51.  This will trigger the error.

This is also happening when using a TabBar as a component.  It seems to be related to fetching the mouse position for a mouse hover event.  It produces errors like
core/math/basis.cpp:47 - Condition "det == 0" is true.
core/math/transform_2d.cpp:51 - Condition "det == 0" is true.

Related issues where this was reported:

https://github.com/godotengine/godot/issues/47757
https://github.com/godotengine/godot/issues/60287
https://github.com/godotengine/godot/issues/63011
https://github.com/godotengine/godot/issues/63012
https://github.com/godotengine/godot/issues/83558

Okay, but I'm not sure they're related just because det == 0.  This basically just means that at least one of the axes is zero, or both axes are parallel.  For the TabBar, my guess is that Godot is trying to calculate a screen position when the screen size is still (0, 0).


Ticket creation is failing in a fresh installation

Hi,
We are testing the latest release v20230409. The ticket creation is failing at slack contact resolver. We have configured both Slack Contact and Conversation plugin in this instance.
When creating an incident, following error trace is showing up.
ERROR:dispatch.main:'email'
Traceback (most recent call last):
  File "/usr/local/lib/python3.11/site-packages/dispatch/main.py", line 185, in dispatch
    response = await call_next(request)
               ^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/starlette/middleware/base.py", line 84, in call_next
    raise app_exc
  File "/usr/local/lib/python3.11/site-packages/starlette/middleware/base.py", line 70, in coro
    await self.app(scope, receive_or_disconnect, send_no_error)
  File "/usr/local/lib/python3.11/site-packages/starlette/middleware/base.py", line 108, in __call__
    response = await self.dispatch_func(request, call_next)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/dispatch/main.py", line 176, in dispatch
    raise e from None
  File "/usr/local/lib/python3.11/site-packages/dispatch/main.py", line 168, in dispatch
    response = await call_next(request)
               ^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/starlette/middleware/base.py", line 84, in call_next
    raise app_exc
  File "/usr/local/lib/python3.11/site-packages/starlette/middleware/base.py", line 70, in coro
    await self.app(scope, receive_or_disconnect, send_no_error)
  File "/usr/local/lib/python3.11/site-packages/sentry_asgi/middleware.py", line 22, in __call__
    raise exc from None
  File "/usr/local/lib/python3.11/site-packages/sentry_asgi/middleware.py", line 19, in __call__
    await self.app(scope, receive, send)
  File "/usr/local/lib/python3.11/site-packages/starlette/middleware/base.py", line 108, in __call__
    response = await self.dispatch_func(request, call_next)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/dispatch/main.py", line 144, in db_session_middleware
    raise e from None
  File "/usr/local/lib/python3.11/site-packages/dispatch/main.py", line 142, in db_session_middleware
    response = await call_next(request)
               ^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/starlette/middleware/base.py", line 84, in call_next
    raise app_exc
  File "/usr/local/lib/python3.11/site-packages/starlette/middleware/base.py", line 70, in coro
    await self.app(scope, receive_or_disconnect, send_no_error)
  File "/usr/local/lib/python3.11/site-packages/starlette/middleware/exceptions.py", line 79, in __call__
    raise exc
  File "/usr/local/lib/python3.11/site-packages/starlette/middleware/exceptions.py", line 68, in __call__
    await self.app(scope, receive, sender)
  File "/usr/local/lib/python3.11/site-packages/fastapi/middleware/asyncexitstack.py", line 21, in __call__
    raise e
  File "/usr/local/lib/python3.11/site-packages/fastapi/middleware/asyncexitstack.py", line 18, in __call__
    await self.app(scope, receive, send)
  File "/usr/local/lib/python3.11/site-packages/starlette/routing.py", line 718, in __call__
    await route.handle(scope, receive, send)
  File "/usr/local/lib/python3.11/site-packages/starlette/routing.py", line 276, in handle
    await self.app(scope, receive, send)
  File "/usr/local/lib/python3.11/site-packages/starlette/routing.py", line 66, in app
    response = await func(request)
               ^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/fastapi/routing.py", line 237, in app
    raw_response = await run_endpoint_function(
                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/fastapi/routing.py", line 165, in run_endpoint_function
    return await run_in_threadpool(dependant.call, **values)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/starlette/concurrency.py", line 41, in run_in_threadpool
    return await anyio.to_thread.run_sync(func, *args)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/anyio/to_thread.py", line 31, in run_sync
    return await get_asynclib().run_sync_in_worker_thread(
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/anyio/_backends/_asyncio.py", line 937, in run_sync_in_worker_thread
    return await future
           ^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/anyio/_backends/_asyncio.py", line 867, in run
    result = context.run(func, *args)
             ^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/dispatch/incident/views.py", line 124, in create_incident
    incident = create(db_session=db_session, incident_in=incident_in)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/dispatch/incident/service.py", line 205, in create
    participant_flows.add_participant(
  File "/usr/local/lib/python3.11/site-packages/dispatch/participant/flows.py", line 34, in add_participant
    individual = individual_service.get_or_create(
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/dispatch/individual/service.py", line 91, in get_or_create
    individual_info = contact_plugin.instance.get(email, db_session=db_session)
                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/dispatch/decorators.py", line 123, in wrapper
    return func(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/dispatch/decorators.py", line 106, in wrapper
    result = func(*args, **kwargs)
             ^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/dispatch/plugins/dispatch_slack/plugin.py", line 275, in get
    "email": profile["email"],
             ~~~~~~~^^^^^^^^^
KeyError: 'email'
INFO:     <IP_ADDRESS>:48440 - "POST /default/incidents HTTP/1.1" 500 Internal Server Error

We have cross checked the Slack configuration in Dispatch. It is correct.

Thanks for reporting this. Take a look at this note in the Slack documentation related to the API endpoint this code uses:
https://api.slack.com/methods/users.profile.get#email-addresses

Does this resolve the issue?

The bot that I am using do have these permissions. But am still facing this issue
bookmarks:write
channels:history
channels:manage
channels:read
chat:write
commands
files:read
groups:history
groups:read
groups:write
im:history
im:read
im:write
mpim:history
mpim:read
mpim:write
pins:write
reactions:read
reactions:write
reminders:write
remote_files:read
remote_files:share
remote_files:write
team:read
usergroups:read
usergroups:write
users.profile:read
users:read
users:read.email
users:write

Just to confirm, the Email Display setting is checked in your Slack Admin settings as well? If so, could you share an example output of what the profile dictionary you receive is? That will help a lot to troubleshoot this. Otherwise, I have a fix ready for this issue that I'll merge tomorrow: https://github.com/Netflix/dispatch/pull/3344

Unfortunately, I dont have admin access on our Slack space. However, I can verify that as a normal user, I can see email address of other users form their profile in slack.
Here is the masked output from users.info api test for your reference:

Thanks. Issue is resolved now.


Why oldDotL are set by DstPoints ?

Could you help explain the following contradiction?
According to the paper, w_k is defined with respect to the fiducial point(control point) p_k, and hence oldDotL should represent the fiducial point here:
https://github.com/Canjie-Luo/Text-Image-Augmentation/blob/ab8e37a161ac5b3f7bc77962bbe5216e88118605/src/imgwarp_mls_similarity.cpp#L59-L60
But instead oldDotL are set with the deformed positions:
https://github.com/Canjie-Luo/Text-Image-Augmentation/blob/ab8e37a161ac5b3f7bc77962bbe5216e88118605/src/imgwarp_mls.cpp#L92-L98
https://github.com/Canjie-Luo/Text-Image-Augmentation/blob/ab8e37a161ac5b3f7bc77962bbe5216e88118605/src/Augment.cpp#L41-L53

Just realize the mapping from deformed space to source space.


[FEATURE] Add ability to configure universal tags for Azure Resources

Describe the bug
Using development container, I cannot create the deployment due to the policy set by company- needs tags

Expected behavior
Deployment goes through
Screenshots
If applicable, add screenshots to help explain your problem.
Desktop (please complete the following information):

OS: Windows10 Enterprise
Version 22H2

Additional context
Need a way to modify deployment to pass the needed tags.

Hi @bdailey-WWT - this isn't really a bug, so I changed it to a feature request to be able to configure universal tags for all created Azure Resources.
Your organization seems to have put an Azure Policy in place to prevent resources from being created without some sort of tag. This is a very common governance pattern.
You can go and manually add tags to the Azure resource deployments in the bicep files under the infra folder. Here's an example of what it would look like:
resource myResource 'Microsoft.Storage/storageAccounts@2021-04-01' = {
  name: 'myStorageAccount'
  location: resourceGroup().location
  tags: {
    environment: 'production'
    owner: 'teamA'
  }
  properties: {
    ...
  }
}

thanks for the heads up. Wasnt sure if it was already a feature and I was missing anything!


Fix vendor dropdown for RerunFlakyTest

The dropdown ended up being a list of a list, though it should only be a list.

@bot-gradle test and merge

Your PR is queued. See the queue page for details.

OK, I've already triggered a build for you.


test(engine): fix executor manager heartbeat timing bug in unit test

What problem does this PR solve?

Issue Number: close #5739
What is changed and how it works?
The unstable test fails because executor-2 could be offline before it sends a new heartbeat.
Add a background heartbeat goroutine to send heartbeat periodically
Check List
Tests

Unit test

Questions
Will it cause performance regression or break compatibility?
Do you need to update user documentation, design documentation or monitoring documentation?
Release note
None

/run-check-issue-triage-complete

Codecov Report

Merging #5876 (74f7dc3) into master (6a451ea) will increase coverage by 0.0671%.
The diff coverage is 55.9440%.

Flag
Coverage Δ

cdc
62.2273% <44.1176%> (+0.2473%)
:arrow_up:

dm
51.9231% <38.0952%> (-0.0070%)
:arrow_down:

engine
62.2082% <64.7727%> (+0.0235%)
:arrow_up:

Flags with carried forward coverage won't be shown. Click here to find out more.
@@               Coverage Diff                @@
##             master      #5876        +/-   ##
================================================
+ Coverage   57.0764%   57.1435%   +0.0671%
================================================
  Files           682        677         -5
  Lines         80224      79820       -404
================================================
- Hits          45789      45612       -177
+ Misses        30146      29951       -195
+ Partials       4289       4257        -32


Issue480: allow comments in angular.json file

PR Checklist
Please check if your PR fulfills the following requirements:

[x ] The commit message follows our guidelines: https://github.com/scullyio/scully/blob/master/CONTRIBUTING.md#commit
[x ] Tests for the changes have been added (for bug fixes / features)
[ ] Docs have been added / updated (for bug fixes / features)

PR Type
What kind of change does this PR introduce?

[ ] Bugfix
[x ] Feature
[ ] Code style update (formatting, local variables)
[ ] Refactoring (no functional changes, no api changes)
[ ] Other... Please describe:

What is the current behavior?

Issue Number: 480
What is the new behavior?
Allow comments in angular.json file with Scully schematics
In fact allow json5 syntax as Angular itself.
Note. ATM json5 is allowed only with angular.json files. But it'd be very easy to extend it to any json file of your choice.
Does this PR introduce a breaking change?

[ ] Yes
[ x] No

Other information

This pr has been cancelled. See now pr #550


Allow all creds to be set in chef-server.rb

Signed-off-by: Steven Danna<EMAIL_ADDRESS>

Untested, just opening for discussion

I liked that, so it's been cherry-picked (8b7aa5efdcd01af35bea9e0f35a2b0a33c4fc51e) in #1137.

👍 closing this


Command 'mraa-gpio set' fails randomly on Joule

Using mraa gpio set command in terminal to set a GPIO pin randomly fails (about 1% of the time) causing an error and not changing the GPIO pin state. Tested it using Yocto based Intel Refkit image and Joule BIOS version 161. Also tried different GPIO pins with the same result. There were no errors when using Minnowboard Turbot and the same image. Error message with Joule:
*** Error in `mraa-gpio': free(): invalid pointer: 0x00000000006193f5 ***
======= Backtrace: =========
/lib/libc.so.6(+0x7039b)[0x7f34b9aa739b]
/lib/libc.so.6(+0x76826)[0x7f34b9aad826]
/lib/libc.so.6(+0x7701e)[0x7f34b9aae01e]
/usr/lib/libmraa.so.1(mraa_find_i2c_bus_pci+0x22f)[0x7f34b9ddc77f]
/usr/lib/libmraa.so.1(mraa_gt_tuchuck_board+0xd0)[0x7f34b9df0d60]
/usr/lib/libmraa.so.1(mraa_x86_platform+0x3c3)[0x7f34b9de8753]
/usr/lib/libmraa.so.1(imraa_init+0x1ef)[0x7f34b9ddb8cf]
/lib/ld-linux-x86-64.so.2(+0xf1ba)[0x7f34ba00c1ba]
/lib/ld-linux-x86-64.so.2(+0xf2cb)[0x7f34ba00c2cb]
/lib/ld-linux-x86-64.so.2(+0xc7a)[0x7f34b9ffdc7a]
======= Memory map: ========
00400000-00403000 r-xp 00000000 b3:03 4655                               /usr/bin/mraa-gpio
00602000-00603000 r--p 00002000 b3:03 4655                               /usr/bin/mraa-gpio
00603000-00604000 rw-p 00003000 b3:03 4655                               /usr/bin/mraa-gpio
00604000-00625000 rw-p 00000000 00:00 0                                  [heap]
7f34b4000000-7f34b4021000 rw-p 00000000 00:00 0
7f34b4021000-7f34b8000000 ---p 00000000 00:00 0
7f34b8fd7000-7f34b8fed000 r-xp 00000000 b3:03 4308                       /lib/libgcc_s.so.1
7f34b8fed000-7f34b91ec000 ---p 00016000 b3:03 4308                       /lib/libgcc_s.so.1
7f34b91ec000-7f34b91ed000 r--p 00015000 b3:03 4308                       /lib/libgcc_s.so.1
7f34b91ed000-7f34b91ee000 rw-p 00016000 b3:03 4308                       /lib/libgcc_s.so.1
7f34b91ee000-7f34b9202000 r-xp 00000000 b3:03 4299                       /lib/libnsl-2.25.so
7f34b9202000-7f34b9402000 ---p 00014000 b3:03 4299                       /lib/libnsl-2.25.so
7f34b9402000-7f34b9403000 r--p 00014000 b3:03 4299                       /lib/libnsl-2.25.so
7f34b9403000-7f34b9404000 rw-p 00015000 b3:03 4299                       /lib/libnsl-2.25.so
7f34b9404000-7f34b9406000 rw-p 00000000 00:00 0
7f34b9406000-7f34b940d000 r-xp 00000000 b3:03 887                        /lib/libnss_compat-2.25.so
7f34b940d000-7f34b960c000 ---p 00007000 b3:03 887                        /lib/libnss_compat-2.25.so
7f34b960c000-7f34b960d000 r--p 00006000 b3:03 887                        /lib/libnss_compat-2.25.so
7f34b960d000-7f34b960e000 rw-p 00007000 b3:03 887                        /lib/libnss_compat-2.25.so
7f34b960e000-7f34b9618000 r-xp 00000000 b3:03 10396                      /usr/lib/libjson-c.so.2.0.1
7f34b9618000-7f34b9817000 ---p 0000a000 b3:03 10396                      /usr/lib/libjson-c.so.2.0.1
7f34b9817000-7f34b9818000 r--p 00009000 b3:03 10396                      /usr/lib/libjson-c.so.2.0.1
7f34b9818000-7f34b9819000 rw-p 0000a000 b3:03 10396                      /usr/lib/libjson-c.so.2.0.1
7f34b9819000-7f34b9832000 r-xp 00000000 b3:03 4295                       /lib/libpthread-2.25.so
7f34b9832000-7f34b9a31000 ---p 00019000 b3:03 4295                       /lib/libpthread-2.25.so
7f34b9a31000-7f34b9a32000 r--p 00018000 b3:03 4295                       /lib/libpthread-2.25.so
7f34b9a32000-7f34b9a33000 rw-p 00019000 b3:03 4295                       /lib/libpthread-2.25.so
7f34b9a33000-7f34b9a37000 rw-p 00000000 00:00 0
7f34b9a37000-7f34b9bcb000 r-xp 00000000 b3:03 2444                       /lib/libc-2.25.so
7f34b9bcb000-7f34b9dca000 ---p 00194000 b3:03 2444                       /lib/libc-2.25.so
7f34b9dca000-7f34b9dce000 r--p 00193000 b3:03 2444                       /lib/libc-2.25.so
7f34b9dce000-7f34b9dd0000 rw-p 00197000 b3:03 2444                       /lib/libc-2.25.so
7f34b9dd0000-7f34b9dd4000 rw-p 00000000 00:00 0
7f34b9dd4000-7f34b9dfb000 r-xp 00000000 b3:03 6198                       /usr/lib/libmraa.so.1.5.1
7f34b9dfb000-7f34b9ffb000 ---p 00027000 b3:03 6198                       /usr/lib/libmraa.so.1.5.1
7f34b9ffb000-7f34b9ffc000 r--p 00027000 b3:03 6198                       /usr/lib/libmraa.so.1.5.1
7f34b9ffc000-7f34b9ffd000 rw-p 00028000 b3:03 6198                       /usr/lib/libmraa.so.1.5.1
7f34b9ffd000-7f34ba020000 r-xp 00000000 b3:03 4292                       /lib/ld-2.25.so
7f34ba211000-7f34ba213000 rw-p 00000000 00:00 0
7f34ba21c000-7f34ba21f000 rw-p 00000000 00:00 0
7f34ba21f000-7f34ba220000 r--p 00022000 b3:03 4292                       /lib/ld-2.25.so
7f34ba220000-7f34ba221000 rw-p 00023000 b3:03 4292                       /lib/ld-2.25.so
7f34ba221000-7f34ba222000 rw-p 00000000 00:00 0
7fffe40f8000-7fffe4119000 rw-p 00000000 00:00 0                          [stack]
7fffe41ac000-7fffe41ae000 r--p 00000000 00:00 0                          [vvar]
7fffe41ae000-7fffe41b0000 r-xp 00000000 00:00 0                          [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0                  [vsyscall]
Aborted (core dumped)

So that's a bit odd, especially if it doesn't happen all the time, it looks like it fails in the init phases whilst trying to probe i2c busses. Is it possible to get a proper gdb backtrace to see what line it fails at? Obviously the fail is somewhere here: https://github.com/intel-iot-devkit/mraa/blob/master/src/mraa.c#L932 but hard to tell exactly where. It's also very odd that it's semi random...

@Propanu you seen this at all with your recent Joule playing?

I've used it a bit recently, with BIOS 193 but working on UART stuff, haven't noticed any init problems, FWIW.

@arfoll To my knowledge the 161 is the newest public BIOS version but I tried with 193 and also with newest 1A0 BIOS version and the problem seemed to persist. I also tried mraa with Ubuntu 16.04 and couldn't get the error with 1000 tries. So the problem seems to be related to Refkit.

@skuusela likely there is an error condition not being handled somewhere in sysfs, can you find out exactly on which lines it blows up with gdb? I can't imagine the fix will be too difficult but it's odd it's not reproducable all the time...
@arunlee77 why are non public bioses being tested and patches submitted against those?

@arfoll Yes, I'll try with gdb. Just need to build an image with it. Maybe testing with non public BIOS version makes sense as when they get released publicly everything already works with them?

@arfoll  For the GPIO patch i submitted, the mapping is valid for older BIOSes and Ostro images.

@arunlee77 ok happy to hear that.

@arfoll #673 solves the random crashing issue with Joule. Also tagging @ipuustin as he helped me with the issue.


Cleaning up NodeBundle, and some slight UI module re-organization

Objective
NodeBundle contains an image field, which can be misleading, because if you do supply an image there, nothing will be shown to screen. You need to use an ImageBundle instead.
Solution

image (UiImage) field is removed from NodeBundle,
extraction stage queries now make an optional query for UiImage, if one is not found, use the image handle that is used as a default by UiImage: https://github.com/bevyengine/bevy/blob/c019a60b39c5683656025bc9d24a02744aa59dea/crates/bevy_ui/src/ui_node.rs#L464
touching up docs for NodeBundle to help guide what NodeBundle should be used for
renamed entity.rs to node_bundle.rs as that gives more of a hint regarding the module's purpose
separating camera_config stuff from the pre-made UI node bundles so that node_bundle.rs makes more sense as a module name.

This is technically a breaking change but I don't think it needs a migration guide.

@bzm3r those doc links are genuinely broken :)


docs: creating nested models

Changes:

[x] add info on working with nested models
[x] add docs folder

hey @maaslalani great suggestion. I actually found some typos while moving the code over to an example :joy: what do you think about these changes? I feel like these docs will become more substantial as we get more questions and as we get feedback. Just pushed the latest changes

Looks awesome @bashbunni !!!

tbd in dev meeting. I'd like some feedback on writing effective comments in the code and whether or not this example should use tea.Batch or return commands. I feel like returning commands makes the flow a bit more obvious, but using tea.Batch is the cleaner solution. I can make this PR a single commit as well if that's preferred.

This example no longer manages state from a main model. That is shown in the composable-view branch.


Stoping propagation of AUTHENTICATION_SUCCESS before dispatching it.

Here https://github.com/lexik/LexikJWTAuthenticationBundle/blob/master/Security/Http/Authentication/AuthenticationSuccessHandler.php#L52 is called setResponse method which internally calls Symfony\Component\HttpKernel\Event\GetResponseEvent::stopPropagation then the event is dispatched and stopped on first listener it reaches.
Is this expected beahavior?

Hello.
This is indeed not the way it should work and it is not the way it worked at the beginning of the project.
I'll try to fix it, in the meantime feel free to make a PR.


Report only unique warnings

Pull Request Description
This change makes sure that reported warnings are unique, based on the value of internal clock tick and ignoring differences in reassignments.
The Warning.get_all is the main entry point to all requests for values' warnings. So rather than implementing de-duplication all over the place, we just do it in one place. There is a cost involved in deduplication (sorting, copying the array + going over the whole array) but that seems like an acceptable cost.
Before:

After:

On the positive side, no further changes, like in LS, have to be done.
Closes #6257.
Important Notes
Alternatively we could consider a more flexible underlying storage of warnings (ArrayRope is not the best choice).
Checklist
Please ensure that the following checklist has been satisfied before submitting the PR:

[x] Screenshots/screencasts have been attached, if there are any visual changes. For interactive or animated visual changes, a screencast is preferred.
[x] All code follows the
Scala,
Java,
and
Rust
style guides. In case you are using a language not listed above, follow the Rust style guide.
All code has been tested:

[x] Unit tests have been written where possible.
[x] If GUI codebase was changed, the GUI was tested when built using ./run ide build.

Oh, I feel bad like I'm constantly criticising.
But I'm really having doubts if this is the right solution. Can we discuss it?
I think we should deduplicate the warnings when adding/combining them.
Otherwise, what this does is it hides the duplication - so from UI perspective it's all good, but the problem still stays under the hood. If the warnings duplicate so easily, they can very easily use a lot of memory. Why keep the duplicates in memory when we can just easily run the deduplication on merge instead?

But I'm really having doubts if this is the right solution. Can we discuss it?
I think we should deduplicate the warnings when adding/combining them.
Otherwise, what this does is it hides the duplication - so from UI perspective it's all good, but the problem still stays under the hood. If the warnings duplicate so easily, they can very easily use a lot of memory. Why keep the duplicates in memory when we can just easily run the deduplication on merge instead?

My first attempt at this PR had uniqueness introduced at all data structures that export getAll, since this unpacking and packing again of warnings is the main source of evil. So that followed more closely to what you are suggesting. But I wasn't convinced this is the right way to go, since this de-duplication would be run on essentially every call. I can explore that more.
Alternatively, I can explore rewriting WithWarning to get rid of ArrayRope.
One potential positive side of this PR, apart from being relatively simple, is that we can still make use of duplicate reassigned warnings, if we ever decide to resurrect them for the IDE purposes. It won't be possible if we de-duplicate at the insertion.
But first, I also want to add some benchmarks to see how (a large number of) warnings affect simple computations.

OK, it still SOs on a fold with a vector of 10000 warnings. This needs more work.

One potential positive side of this PR, apart from being relatively simple, is that we can still make use of duplicate reassigned warnings, if we ever decide to resurrect them for the IDE purposes. It won't be possible if we de-duplicate at the insertion.

Indeed, I also thought that it may be useful at some point. But I'm afraid the performance drain could be too much. And also, at least currently I'm not quite certain we need it that much from Libs perspective - the major goal is to be able to display a warning when there is a risk of data loss/corruption and be sure that the user can track its source. A single path should be enough for most cases I think.

But first, I also want to add some benchmarks to see how (a large number of) warnings affect simple computations.

That would be ideal.

Btw. looking around the creationTime logic, I'm thinking if we should make the Warning constructors private, to disallow creating a Warning with a custom creationTime - it should always be initialized with ctx.clockTick() or with existing time when creating a reassigned copy of an existing warning. Having the constructors public is a risk that someone may use them wrongly.

sgtm


AWS Lambda

Hi,
I have an API on AWS Lambda that calls OpenAI. I want to monitor calls to OpenAI using Wandb Weave. However; it seems I cannot set it up on AWS Lambda. I have setup a docker image for the API but when I execute the API; it givens me the following error:
START RequestId: b81f396b-1dcd-49c4-925d-640e069d2bfd Version: $LATEST
--
wandb: WARNING Path /var/task/wandb/ wasn't writable, using system temp directory.
wandb: WARNING Path /var/task/wandb/ wasn't writable, using system temp directory
wandb: WARNING Path /var/task/wandb/ wasn't writable, using system temp directory
wandb: Currently logged in as: <username> (<org>). Use `wandb login --relogin` to force relogin
wandb: Tracking run with wandb version 0.16.0
wandb: Run data is saved locally in /tmp/wandb/run-20231109_085849-cwbt0w4l
wandb: Run `wandb offline` to turn off syncing.
wandb: Syncing run comic-voice-23
wandb: ⭐ View project at https://wandb.ai/<org>/<proj>
wandb: 🚀 View run at https://wandb.ai/<org>/<proj>/runs/<id>
[ERROR] LifespanFailure: Lifespan startup failure. Traceback (most recent call last):
File "/var/lang/lib/python3.11/site-packages/starlette/routing.py", line 677, in lifespan
async with self.lifespan_context(app) as maybe_state:
File "/var/lang/lib/python3.11/site-packages/starlette/routing.py", line 566, in __aenter__
await self._router.startup()
File "/var/lang/lib/python3.11/site-packages/starlette/routing.py", line 656, in startup
handler()
File "/var/task/main.py", line 42, in startup_event
init_monitor(f"{entity}/{project}/{stream}")
File "/var/lang/lib/python3.11/site-packages/weave/monitoring/monitor.py", line 322, in init_monitor
stream_table = _init_monitor_streamtable(stream_key)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/var/lang/lib/python3.11/site-packages/weave/monitoring/monitor.py", line 291, in _init_monitor_streamtable
stream_table = StreamTable(
^^^^^^^^^^^^
File "/var/lang/lib/python3.11/site-packages/weave/wandb_interface/wandb_stream_table.py", line 247, in __init__
super().__init__(
File "/var/lang/lib/python3.11/site-packages/weave/wandb_interface/wandb_stream_table.py", line 161, in __init__
self._ensure_remote_initialized()
File "/var/lang/lib/python3.11/site-packages/weave/wandb_interface/wandb_stream_table.py", line 174, in _ensure_remote_initialized
self._weave_stream_table_ref = storage._direct_publish(
^^^^^^^^^^^^^^^^^^^^^^^^
File "/var/lang/lib/python3.11/site-packages/weave/storage.py", line 133, in _direct_publish
artifact = artifact_wandb.WandbArtifact(name, type=wb_artifact_type_name)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/var/lang/lib/python3.11/site-packages/weave/artifact_wandb.py", line 410, in __init__
self.io_service = io_service.get_sync_client()
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/var/lang/lib/python3.11/site-packages/weave/io_service.py", line 647, in get_sync_client
return SyncClient(get_server(), filesystem.get_filesystem())
^^^^^^^^^^^^
File "/var/lang/lib/python3.11/site-packages/weave/io_service.py", line 413, in get_server
SERVER = Server(process=False)
^^^^^^^^^^^^^^^^^^^^^
File "/var/lang/lib/python3.11/site-packages/weave/io_service.py", line 186, in __init__
self._shutting_down = multiprocessing.Event()
^^^^^^^^^^^^^^^^^^^^^^^
File "/var/lang/lib/python3.11/multiprocessing/context.py", line 93, in Event
return Event(ctx=self.get_context())
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/var/lang/lib/python3.11/multiprocessing/synchronize.py", line 331, in __init__
self._cond = ctx.Condition(ctx.Lock())
^^^^^^^^^^
File "/var/lang/lib/python3.11/multiprocessing/context.py", line 68, in Lock
return Lock(ctx=self.get_context())
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/var/lang/lib/python3.11/multiprocessing/synchronize.py", line 169, in __init__
SemLock.__init__(self, SEMAPHORE, 1, 1, ctx=ctx)
File "/var/lang/lib/python3.11/multiprocessing/synchronize.py", line 57, in __init__
sl = self._semlock = _multiprocessing.SemLock(
^^^^^^^^^^^^^^^^^^^^^^^^^
OSError: [Errno 38] Function not implemented
Traceback (most recent call last):  File "/var/lang/lib/python3.11/site-packages/mangum/adapter.py", line 80, in __call__    stack.enter_context(lifespan_cycle)  File "/var/lang/lib/python3.11/contextlib.py", line 505, in enter_context    result = _enter(cm)  File "/var/lang/lib/python3.11/site-packages/mangum/protocols/lifespan.py", line 69, in __enter__    self.loop.run_until_complete(self.startup())  File "/var/lang/lib/python3.11/asyncio/base_events.py", line 653, in run_until_complete    return future.result()  File "/var/lang/lib/python3.11/site-packages/mangum/protocols/lifespan.py", line 167, in startup    raise LifespanFailure(self.exception)
END RequestId: b81f396b-1dcd-49c4-925d-640e069d2bfd
REPORT RequestId: b81f396b-1dcd-49c4-925d-640e069d2bfd	Duration: 5255.93 ms	Billed Duration: 13811 ms	Memory Size: 512 MB	Max Memory Used: 504 MB	Init Duration: 8554.29 ms

Can someone help me to solve this?
Regards

Hello @NaxAlpha! Thank you for the issue. We have spent the last few months completely rewriting Weave and have a new monitoring tool available. Please check out wandb.me/weave for docs and tutorials. The underlying architecture has completely changed and I suspect your use case is supported now.


Rewrite the embedded HTTP server in Swift

Fixed #17

@fernandodev, any comments or suggestions?

Sorry for delay.


Validation and Tests for Arithmetic Rules

PR up: https://github.com/linqs/psl/pull/14

Complete in this fork.
Will be merged into PSL formal.


Fixed lighting bug with Vintagium

Probably related to #40
📝 Description
We can't rely on vanilla's ChunkRenderDispatcher while using Vintagium. Change is similar to commit ->  https://github.com/Asek3/sodium-1.12/commit/d947ba573dfd8ab91afa1fe50455ab41326563da

Summary by CodeRabbit

New Features

Added compatibility check for the "vintagium" mod to enhance material loading conditions.

I see, I have some work to do before releasing the new version, which hopefully should release Friday, I will merge this into it right before release.
Thank you for taking the time to add compatibility.


Implement <string>.replace_regex(<pattern>, <replacement>)

from {x: "foobarbaz"}
y = x.replace_regex("a|o", "?")'

{
  "x": "foobarbaz",
  "y": "f??b?rb?z"
}

I would prefer to simply have pattern-based overload and just call it replace(.) for simplicity

I thought about this as well, but couldn't come up with a nice way to get both done in one function without a pattern literal.

Right, I think this is nice to have right now, even if we add a pattern literal in the future. We can always deprecate and then remove this function especially in such an early phase.


[Feature Request] Doc revamp

Motivation
Plan for the doc revamp

[x] A 0-to-1 tutorial or Getting started #861
[x] A tutorial on building a custom env #911
[ ] A tutorial on model ensembling #876
[ ] A tutorial on multi-agent #862
[ ] PPO tutorial

Hi there. We are building a multi-agent environment based on Nvidia Isaac Gym and want to integrate it with torchrl somehow. So we are more than glad to help with 2. and 3., and thus would like to know your idea on what a multi-agent interface should look like and how and where ensembling could take place accordingly.
The solution should be general enough to cover the following cases:

homogeneous/heterogenous agents
cooperative/competitive/mixed games
synchronous/turn-based gameplay (as asynchronous ones are less studied)

The first to-be-addressed questions I can think of:

Env: what are the rules for defining the tensor_specs for multiple agents?
Collector: how should we structure a joint policy and perform data collection?

Specifically for the example/tutorial, I think multi-agent PPO with actors of the same structure (so we can showcase model ensembling) and a single centralized critic could be a good one.
What do you think?

This sounds wonderful.
We're actively working with @matteobettini on refactoring the API to make it more MARL friendly. We're also getting support from Nvidia to integrate Isaac sim.
The stars are clearly aligned 😀
The ambition I have for MARL and multitask is to treat envs like we treat tensors: being able to stack them, or perhaps in some cases to index them. The specs would follow a similar logic: you can already expand specs, in the future I'd like to be able to stack them (even if heterogeneous, like we do with tensordict).
I'll ping you as the work goes on, I'd love to get feedback on these features.
On your side let me know how I can help!

@btx0424
That is also my goal! I especially like that you mentioned heterogeneus agents which is a particularly important for me.
Here is a list of issues me and @vmoens have focused on to pave the way to multi-agent #777 .
Some of them are still open, such as multi-agent collectors.
Happy to discuss the next steps and curious about any suggestion

I can see that you have made impressive efforts to keep everything in a (nested-) tensor-like structure, and tensor_spec is currently the next step.
After reading through #777, the things that come into my mind are:

We should allow per-agent done in addition to the environment-level done: There are cases that some agents die before others, e.g., a unit gets destroyed in SMAC, where the later invalid transitions should not be used for training.
Assuming a vectorized multi-agent Env to have size [n_vec_envs, n_agents] may have limitations. It is common in MARL to provide some privileged information (e.g., a global state) to a centralized critic. Generally, the shapes are still only homogeneous up to  [n_vec_envs, *].

As I understand, here we are faced with whether to provide an AgentSpec abstraction.

When constructing the policy for an Env, it is natural to parse the individual specs without the prepended [*, n_agents] dimensions. It is easier to expand the agent level spec to Env level spec than the other way around.
With TensorDictModule, a natural way to think of agent-policy identification is to name the agents and set in_keys and out_keys correspondingly. This could be easily achieved with a Transform from the stacking-and-indexing way (and vice versa), though.
If we do not provide a AgentSpec or similar abstraction at the environment level then it makes less sense to have env.n_agents and hence the batch size [n_vec_envs, n_agents].
Also, If not, the users themselves have to ensure the ordering of the stacking and later do correct indexing. Overall this become confusing for inexperienced users.

A solution would be providing an AgentSpec abstraction with which individual specs are specified. And later we expand and stack them in EnvBase.__setattr__ for the user upon self.some_agent=AgentSpec(...), ensuring everything looks correct.
Nonetheless, I'm definitely a fan of the stacking-and-indexing way now. In MARL we sometimes want a policy pool or something like the league training in AlphaStar. Essentially it is executing policies with the same structure but different params or states. Imagine we can

index a vectorized Env and assign SubEnvs to different SubCollectors
these SubCollectors share the same policy structure, but just should be using different params
stack the SubCollectors and do parallel inference with functorch.vmap
save all the overhead of having to do a for loop to perform operations that could be parallelized

We should allow per-agent done in addition to the environment-level done: There are cases that some agents die before others, e.g., a unit gets destroyed in SMAC, where the later invalid transitions should not be used for training.

Does this imply something different than a done state with a shape that matches the env shape?

It is common in MARL to provide some privileged information (e.g., a global state) to a centralized critic.

that's an interesting point. IIUC you're saying that an env with a batch size [B] should be able to send and receive information that has an empty shape[]?
Can we get around this by expanding the common information? torch.expand does not allocate memory so that should not be an issue. But I may be missing the point here

provide an AgentSpec abstraction

I'm not entirely sure of what this would look like.
Here's my take on envs and specs: beyond field-specific commitments, I think that it is natural to think about populations of envs as something that we can group with torch. Stack. #892 will provide this functionality for specs. Eventually, I would like to be able to stack and index specs in a way that feels natural. That could also allow us to build training loops where agents are dynamically added or removed (we're not there yet but it would be cool).
I'm not sure I see what an AgentSpec would be? Can you elaborate of what it would contain? Would it be strictly a MARL thing?
Agent is a bit overused and I'm always confused about what it means (sometimes ppl talk about an agent as an algorithm, sometimes as an actor, sometimes as something completely different), hence I try to avoid it in torchrl. If we have a crystal clear definition on what it is and what it isn't i'm happy to adopt it ;)

Also, If not, the users themselves have to ensure the ordering of the stacking and later do correct indexing. Overall this become confusing for inexperienced users.

This makes me curious. Why would it be confusing? What is the alternative?
I know sometimes agents are sort of "named" in a dictionary but that seems hardly scalable and reusable to me. Also, it is a strong commitment to MARL: even though I'm super excited about supporting MARL I would like that someone doing something completely different (say, offline RL or bandits) is not faced with things that originate from other domains.
Again, I'm not saying we don't want our API to be challenged, on the contrary, but I'm wondering what the alternative would be. I tend to think that the concept of indexable envs can group together MARL, multi-task, or even just distributed RL.
Anyhow: I'm super excited to see how productive these conversations are!
cc @PaLeroy FYI

@btx0424 thanks for taking the time to read through everything. You made many interesting points, let me start addressing a few.

per-agent dones is already available and is the main reason why agents are in the batch_si ze. Since done does not have a spec this was the only way. This consequently also allows to have a per_agent reset flag.
I understand that the   sharing of a common state might be a worry. One could solve it with a repeat() (very memory inefficient) or, better, as @vmoens mentioned, with an expanded view (we should definitely think of implementing this). Also, having a per-gent global state sometimes might be needed in case we are using centralised training but each agent has a different global state
if agents are in the batch_size, we can ask collectors if we want to collect per_agent frames or per_team frames. While if we keep them out we will always get per_team frames

I also really like the point of being able to assign different policies to different sub-envs , sub-tasks or agents. So this would mean passing to a collector a bunch of policies each with a slice of the env it should operate on.

This dilemma of having the agents is the batch_size or not has been following me for  a while and I am curious to get everyone’s thoughts early on to see if it is worth going this way ors just having the agents as a dimension oitside the batch_size. Here are the pro and cons i can think of:
PROS

per_agent done and reset (to do this outside the batch_size we would need reset and done to have a spec)
per_agent or per_team collection option
More systematic

CONS

you have to create an expanded view when something is shared across a dimension
mixing of logics in the batch_size. (Some part of the batch_size is for parallel and vectorized envs and some for agents). To inform algorithms of what is what we would have to carry a mask forward.

I also really like the point of being able to assign different policies to different sub-envs , sub-tasks or agents. So this would mean passing to a collector a bunch of policies each with a slice of the env.batch_size it should operate on.

This is supported by TensorDictSequential provided that agents have observation keys that differ: the module will route the observations to the appropriate policy as needed. It also supports parameter tying and vmap.

Replaying to @vmoens and #897.

Are you saying that, in your opinion, the first thing someone should be taught about is how to build an environment from scratch?

I wouldn't say that. I think the agent shouldn't have any contact with the env code variable. And that the env shouldn't have to be derived from a base class. Like in the tutorial in the following code:
def make_ddpg_actor(
    stats,
    device="cpu",
):
    proof_environment = make_transformed_env(make_env(), stats)

    env_specs = proof_environment.specs
    out_features = env_specs["action_spec"].shape[0]

...

 distribution_kwargs={
            "min": env_specs["action_spec"].space.minimum,
            "max": env_specs["action_spec"].space.maximum,
        },

I think the agent should not get the entire env object but just the bare minimum of information it needs to construct the networks - the state and action shape and maybe the action min/max(but maybe not even that, it could just output [-1, 1] and then it would be up to the user to put that into the correct range). This would eliminate the need for the environment to be changed to fit a certain interface and would put all the responsibility on the programmer which I find more intuitive.

I would guess that many newcomers would like to get their hands on a more "concrete" and pre-packed problem like solving an existing task (ie a gym environment or similar).

Hmm. I actually don't know. You might be right. Personally, I feel like I've always had an environment I wanted to work on and found the Gym envs annoying to install. I think I'd appreciate more an example that assumes an environment has been loaded already and just applies the agent to it. I know when I was reading torch tutorials that I also never liked loading the built-in datasets like MNIST but liked creating my own data. But to each his own and I might just be weird.

We can definitely do a better job at documenting the single features of the library.
It's sort of a rubiks cube, where you solve one face but it messes up the face on the other side:

If we do tutorials/examples about single features, it is confusing for newcomers as they need to go through multiple tutos to understand how to code a simple "go from A to B" policy.
If we go for the full tutorial, there are quickly too much info to be digested in one go.

I totally get what you're saying. I think little examples directly in the docs page of the object would be the best. Just like how to instantiate the object and how to call it or something. For example like this docs page for MSELoss.
I hope that helped. And thanks for your time, I really appreciate it.

I think the agent should not get the entire env object but just the bare minimum of information it needs to construct the networks - the state and action shape and maybe the action min/max(but maybe not even that, it could just output [-1, 1] and then it would be up to the user to put that into the correct range). This would eliminate the need for the environment to be changed to fit a certain interface and would put all the responsibility on the programmer which I find more intuitive.

Right, but don't read too much in that helper function. This is a simple code snippet aimed at creating an env in a specific context, ie it is not part of the library as a core component. Again: we could do a better job at explaining how to use the primitives, but helper functions should not be seen as indications of how to build a training pipeline. They are merely there to tie the pieces together.

Hmm. I actually don't know. You might be right. Personally, I feel like I've always had an environment I wanted to work on and found the Gym envs annoying to install. I think I'd appreciate more an example that assumes an environment has been loaded already and just applies the agent to it. I know when I was reading torch tutorials that I also never liked loading the built-in datasets like MNIST but liked creating my own data. But to each his own and I might just be weird.

Good to know. I'm working on a "make your own env" tutorial, without the need to install any other library.
I'll ping you when it's done

The picture is getting clearer. I think it's possible to make a unifying API with some effort.
Let's address the problems one by one. Throughout the following discussion, we assume we are dealing with a vectorized multi-agent environment with E envs, two types of agents A1 and A2, and an observation_dim D.
Regarding the batch_size of an Env, I meant something like
import torch
from torchrl.data import CompositeSpec, UnboundedContinuousTensorSpec

E, (A1, A2), D = 1024, (2, 3), 16

obs_spec = torch.stack([
    *[CompositeSpec(obs=UnboundedContinuousTensorSpec(D)) for _ in range(A1)],
    *[CompositeSpec(obs=UnboundedContinuousTensorSpec(D)) for _ in range(A2)],
    CompositeSpec(state=UnboundedContinuousTensorSpec(D * (A1+A2))) # should go to a centralized critic
], dim=0).expand(E, A1+A2+1)
obs_spec.shape # torch.Size([1024, 6])

Another option is to have a separate Env.state_spec. But either way, we are not getting TensorDicts of shape [E, A1+A2]. Here state is not common information for the actors but a privileged information for the critic, so torch.expand does not intuitively solve the issue.
But now I think this is not really a problem and I'll try to show why later. Let's drop the state and proceed. With the above spec, assuming A1 and A2 have the same actor model structure, a wonderful way to construct the joint policy is to stack individual policies. For simplicity, we use the normal nn.Module instead of TensorDictModule.
import torch
import torch.nn as nn
import functorch
from torchrl.data.tensor_specs import UnboundedContinuousTensorSpec
from tensordict import TensorDict
from tensordict.nn import make_functional
from typing import Tuple
from copy import deepcopy

E, (A1, A2),  D = 1024, (2, 3), 16

input_spec = torch.stack([
    *[UnboundedContinuousTensorSpec(D) for _ in range(A1)],
    *[UnboundedContinuousTensorSpec(D) for _ in range(A2)],
], dim=0)

def stack(modules: Tuple[nn.Module, ...]):
    if not len(set(m.__class__ for m in modules)) == 1:
        raise ValueError("Currently only stacking homogeneous modules is supported.")
    params = torch.stack([make_functional(deepcopy(m)) for m in modules])
    m = deepcopy(modules[0])
    make_functional(m)
    func = functorch.vmap(m) # a lot to do here to ensure the desired behavior
    # we might want to assign a `shape` to the "stacked" func
    return func, params

x = input_spec.rand()
a1 = nn.Linear(D, 1)
a2 = nn.Linear(D, 1)

joint_policy, params = stack([
    *[a1 for _ in range(A1)],
    *[a2 for _ in range(A2)]
])

y1 = joint_policy(x, params)
y2 = torch.cat([
    a1(x[:A1]),
    a2(x[A1:])
])

assert torch.allclose(y1, y2, atol=1e-7) # the results are slightly different, though

Ideally, this parallel inference could provide a considerable speedup. It also saves the trouble of having to index the input to do policy-agent matching.

I also really like the point of being able to assign different policies to different sub-envs , sub-tasks or agents. So this would mean passing to a collector a bunch of policies each with a slice of the env.batch_size it should operate on.

This is supported by TensorDictSequential provided that agents have observation keys that differ: the module will route the observations to the appropriate policy as needed. It also supports parameter tying and vmap.

TensordictSequential is of course capable of the job if we index-and-name the input, but the operations are sequential. I think the above share the same spirit with and is the first step to stacking sub-collectors.
As for the AgentSpec abstraction, I have been doing something similar to
from torchrl.envs import EnvBase as _EnvBase
from torchrl.data import TensorSpec
from dataclasses import dataclass
from typing import List

@dataclass
class AgentSpec:
    name: str
    n_agents: int
    observation_spec: TensorSpec
    action_spec: TensorSpec
    reward_spec: TensorSpec

class EnvBase(_EnvBase):

    agent_specs: List[AgentSpec] = []

    def register_agent(
        self, agent_spec: AgentSpec
    ):
        # completely optional
        # 1. the named-agents way
        self.agent_specs.append(agent_spec)
        def expand(spec: TensorSpec):
            return spec.expand(*self.batch_size, agent_spec.n_agents, *spec.shape)
        self.observation_spec[f"{agent_spec.name}.obs"] = expand(agent_spec.observation_spec)
        self.action_spec[f"{agent_spec.name}.action"] = expand(agent_spec.action_spec)
        self.reward_spec[f"{agent_spec.name}.reward"] = expand(agent_spec.reward_spec)
        # 2. the StackedSpec way
        # not sure what it exactly looks like for now, but I believe it is doable and makes good sense

# so that we can do
env = EnvBase(...)
policies = []
for agent_spec in env.agent_specs:
    policies.extend([make_model(agent_spec) for _ in range(agent_spec.n_agents)]) # the more natural individual view
joint_policy = torch.stack(policies)

Putting things together, I think you can see my point about how it makes policy construction more straightforward. By design, we can make this completely optional in case the user wants to specify everything manually. So it won't trouble people outside the MARL context.

But now I think this is not really a problem and I'll try to show why later.
Up to now, we have been assuming a homogeneous setting. However, once we can generalize to heterogeneous cases where we can correctly stack nn.Modules with different structures, it is as straightforward as

obs_spec = torch.stack([
    *[CompositeSpec(obs=UnboundedContinuousTensorSpec(D)) for _ in range(A1)],
    *[CompositeSpec(obs=UnboundedContinuousTensorSpec(D)) for _ in range(A2)],
    CompositeSpec(state=UnboundedContinuousTensorSpec(D * (A1+A2))) # should go to a centralized critic
], dim=0).expand(E, A1+A2+1)

actor_critic = stack([
  *[make_actor(...) for _ in range(A2)],
  *[make_actor(...) for _ in range(A1)]，
  make_critic(...)
])

I have been really getting inspiration from this project and the discussion. It would be great to get started by making an example/tutorial with VMAS once #892 is ready and see what problems might pop out. What do you think?

Regarding the batch_size of an Env, I meant something like
import torch
from torchrl.data import CompositeSpec, UnboundedContinuousTensorSpec

E, (A1, A2), D = 1024, (2, 3), 16

obs_spec = torch.stack([
    *[CompositeSpec(obs=UnboundedContinuousTensorSpec(D)) for _ in range(A1)],
    *[CompositeSpec(obs=UnboundedContinuousTensorSpec(D)) for _ in range(A2)],
    CompositeSpec(state=UnboundedContinuousTensorSpec(D * (A1+A2))) # should go to a centralized critic
], dim=0).expand(E, A1+A2+1)
obs_spec.shape # torch.Size([1024, 6])

Another option is to have a separate Env.state_spec. But either way, we are not getting TensorDicts of shape [E, A1+A2]. Here state is not common information for the actors but a privileged information for the critic, so torch.expand does not intuitively solve the issue.

I think you might have lost me here. Where is D gone? How does that expand shape fit? Are you proposing a batch dimension of size n_agents +1?

Sorry for the delayed reply. The example was coded with the implementation of  #892 at the time. I went back and found that currently, the behavior of stacking CompositeSpec is different from that of non-composite ones:
from torchrl.data import CompositeSpec, UnboundedContinuousTensorSpec

E, (A1, A2),  D = 1024, (2, 3), 16

obs_spec = torch.stack([
    *[CompositeSpec(obs=UnboundedContinuousTensorSpec(D)) for _ in range(A1)],
    *[CompositeSpec(obs=UnboundedContinuousTensorSpec(D)) for _ in range(A2)],
    # CompositeSpec(state=UnboundedContinuousTensorSpec(D * (A1+A2)))
], dim=0)
print(obs_spec.shape) # [A1+A2], so obs_spec.exand(E, A1+A2) works

input_spec = torch.stack([
    *[UnboundedContinuousTensorSpec(D) for _ in range(A1)],
    *[UnboundedContinuousTensorSpec(D) for _ in range(A2)],
], dim=0)
print(input_spec.shape) # [A1+A2, D], have to do input_spec.expand(E, A1+A2, D)

So D is indeed gone in the composite case. I'm unsure which makes more sense here, but I would vote for the first.

Are you proposing a batch dimension of n_agents +1?

No. It is just an example of what commonly happens when we want to provide some additional input that is not of shape [n_agents, *].  This information may or may not be for the actors. So expanding it to [n_agents, *] does not solve the issue in a general way.
So I am proposing:

Leave Env's batch size to be [n_vec_envs] for flexibility. In this case, Collectors are counting environment steps. "Solving a multi-agent game in X environment steps" is a fair way to talk about sample efficiency in the literature and makes enough sense to me.
Add an optional way to register agents to make it more convenient and error-prune to handle the specs and construct policies. It won't break what we already have now.
Leave obs_spec's shape to the result of stacking. Think of the joint policy for rollout as stacked Modules that is consistent with the specs in some way. Apply ensembling to facilitate parallel inference if possible.

Regarding stacking Modules we will need more opinions and help from @vmoens. Assuming agents of the same type share the same actor network, the example I used is memory-inefficient as it makes copies of the same parameters. Also we will have to manully collect the gradients when training.
Ideally it looks like:
a1 = nn.Linear(D, 1)
a2 = nn.Linear(D, 1)
policy = torch.cat([
  a1.expand(A1),
  a2.expand(A2),
]) # returns a lazily concat-ed object
policy.shape # [A1+A2]

So D is indeed gone in the composite case. I'm unsure which makes more sense here, but I would vote for the first.

bouncing back on this: it is only gone because you did not assign a shape to CompositeSpec. If you do
obs_spec = torch.stack([
    *[CompositeSpec(obs=UnboundedContinuousTensorSpec(D), shape=[D]) for _ in range(A1)],
    *[CompositeSpec(obs=UnboundedContinuousTensorSpec(D), shape=[D]) for _ in range(A2)],
], dim=0)

the behaviour is consistent.
For stacking layers, the way we approach this is the following
module1 = TensorDictModule(a1, in_keys=["key1"], out_keys=["embed"])
module2 = TensorDictModule(a2, in_keys=["key2"], out_keys=["embed"])
module = TensorDictSequential(module1, module2, partial_tolerant=True)
data = torch.stack([
    TensorDict({"key1": torch.randn(D)}, []),
    TensorDict({"key2": torch.randn(D)}, [])
], 0)
module(data)

When TensorDictSequential will not find "key1" in your lazy stacked TensorDict, it will decompose it and look for "key1".
In multi-agent settings, you will just need to set a different set of key names for each agent, collect them in a lazy stacked td and pass that to a TensorDictSequential.
That way we can avoid to code stacks of Linear layers, convolutional layers, etc.
Wdyt?

Sorry for the delayed reply. I think that works for me.

I know sometimes agents are sort of "named" in a dictionary but that seems hardly scalable and reusable to me.

In multi-agent settings, you will just need to set a different set of key names for each agent, collect them in a lazy stacked td and pass that to a TensorDictSequential.

Guess in the end we have to give agents names somewhere. But you've managed to make things as easy as possible. That's great!
I will digest this a bit and try to work out a multi-agent PPO example/tutorial that looks similar to the PPO tutorial and demonstrates the ideas we have discussed above.