Block.dstdata not setting data?

Hello! I am trying to write a custom layer for a heterogenous graph and have run into a problem with assigning data to src/dstdata. The issue only seems to crop up when I use batching, it seems to work as expected when I use the full graph.

I’m not sure if I am doing something wrong here, but I don’t understand why the new data is not in g.dstdata.

Thanks in advance!

toy_graph = {('a','a<>b','b') : (torch.tensor([0,0,1,1,2,3,2,3,0]),torch.tensor([0,1,1,2,1,2,3,4,0])),
             ('b','b<>a','a') : (torch.tensor([0,1,1,2,1,2,3,4,3]),torch.tensor([0,0,1,1,2,3,2,3,0]))
}
g = dgl.heterograph(toy_graph)

g.nodes['a'].data['A'] = torch.arange(8).view(4,2).float()
g.nodes['b'].data['B'] = torch.arange(10).view(5,2).float()

# create the sampler
fanouts = [i for i in range(1,3)]
sampler = dgl.dataloading.NeighborSampler(fanouts=fanouts)

# create the training dataloader
train_loader = dgl.dataloading.DataLoader(
    g, 
    {'a':g.nodes('a')}, 
    sampler, 
    batch_size=1, 
    shuffle=True,
)

# create test module
class test(nn.Module):
    def __init__(
            self,
            in_dim,
            out_dim,
    ):
        super().__init__()

        self.A_proj = nn.Linear(in_dim, out_dim , bias = False)
        self.B_proj = nn.Linear(in_dim, out_dim , bias = False)

    def forward(self, g, x):
        with g.local_scope():
            if isinstance(x, tuple):
                x_src , x_dst = x
          
            S = self.A_proj(x_src['A']['a'])
            D = self.B_proj(x_dst['B']['b'])
            
            g.srcdata['A_new'] = {'a' : S}
            g.dstdata['B_new'] = {'b' : D}

            print(g.srcdata.keys())
            print(g.dstdata.keys())

            return g.dstdata['D']

input_nodes, output_nodes, blocks = next(iter(train_loader))

x = (blocks[0].srcdata, blocks[0].dstdata)

test_layer(blocks[0], x)

Output:
dict_keys([‘A’, ‘_ID’, ‘A_new’, ‘B’, ‘B_new’])
dict_keys([‘A’, ‘_ID’, ‘B’])

Hi @AndrewS, this is a known issue https://github.com/dmlc/dgl/issues/3670. You can use g.srcdata.update() as in the issue.

Hi @czkkkkkk thanks for the reply and pointing to the issue.

I tried g.srcdata.update as in the snippet below, but the output is still the same: srcdata is updated with both A_new and B_new, but dstdata has neither. (I also tried with srcdata replaced with dstdata).

g.srcdata.update({'B_new' : {'b' : D}})

I have run into the similar issue with Block.dstdata.
Something went wrong when I wanted to use apply_nodes() to update the dstnodes data. It seems the update process in the model.forward() through
g.dstdata[‘features’] = … doesn’t store the data.
I also tried ntypes = ‘DST/_N’ or v=[:num_dstnodes], ntypes = ‘SRC/_N’
in apply_nodes() and wished they can refer to the updated dstndata, both didn’t work.

Sorry for the late hi @AndrewS , being the first time to use the forum.

Hi @AndrewS, I guess I found something might be of use for you. When you use g.dstdata['B_new'] = {'b' : D} , you were meant to specify the dstdata and then ntype ‘b’ in it, but actually it will somehow recognize it as the ‘b’ only and go to the default srcnodes.
Try g.dstdata['B_new'] = {'DST/b' : D}, which wil eventually point to the destination nodes.

1 Like

Hi @QiYii – that works! Thanks for finding it and sharing it!

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.