{"action":"created","issue":{"url":"https://api.github.com/repos/root-mirror/root/issues/277","repository_url":"https://api.github.com/repos/root-mirror/root","labels_url":"https://api.github.com/repos/root-mirror/root/issues/277/labels{/name}","comments_url":"https://api.github.com/repos/root-mirror/root/issues/277/comments","events_url":"https://api.github.com/repos/root-mirror/root/issues/277/events","html_url":"https://github.com/root-mirror/root/pull/277","id":181319818,"number":277,"title":"First-pass IMT implementation of FlushBaskets.","user":{"login":"bbockelm","id":1093447,"avatar_url":"https://avatars.githubusercontent.com/u/1093447?v=3","gravatar_id":"","url":"https://api.github.com/users/bbockelm","html_url":"https://github.com/bbockelm","followers_url":"https://api.github.com/users/bbockelm/followers","following_url":"https://api.github.com/users/bbockelm/following{/other_user}","gists_url":"https://api.github.com/users/bbockelm/gists{/gist_id}","starred_url":"https://api.github.com/users/bbockelm/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/bbockelm/subscriptions","organizations_url":"https://api.github.com/users/bbockelm/orgs","repos_url":"https://api.github.com/users/bbockelm/repos","events_url":"https://api.github.com/users/bbockelm/events{/privacy}","received_events_url":"https://api.github.com/users/bbockelm/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":6,"created_at":"2016-10-06T04:02:01Z","updated_at":"2016-10-06T20:11:51Z","closed_at":null,"pull_request":{"url":"https://api.github.com/repos/root-mirror/root/pulls/277","html_url":"https://github.com/root-mirror/root/pull/277","diff_url":"https://github.com/root-mirror/root/pull/277.diff","patch_url":"https://github.com/root-mirror/root/pull/277.patch"},"body":"This is based on @dpiparo 's work to parallelize `GetEntry`.  The basic idea is, when we are flushing all active branches, we do each branch in parallel.  We have to maintain mutual exclusion when interacting with the `TTree` or `TFile`, but we can parallelize the compression of the baskets (which is a significant amount of CPU time).\r\n\r\nNote the least satisfactory part of this work is having to use a mutex to access the byte-counters in `TTree`; this is because these fields are serialized and `std::atomic<>` is not serializable.  Any hints as to how to get around this?\r\n\r\nSetting `MainEvent.cxx` in the `test` sub-directory to use this (with LZMA as the compression algorithm), I get:\r\n```\r\nRealTime=76.340815 seconds, CpuTime=131.770000 seconds\r\n```\r\n\r\n@pcanal @Dr15Jones - this spun off from our discussion about CMSSW efficiency.  It's really easy to parallelize `FlushBaskets` using a `tbb::task_group` that I later wait for.  However, continuation-style programming is difficult here because `FlushBaskets` is called from deep callstacks.  Further, there's a lot of state in the basket itself we'd need to unravel.\r\n\r\nLooking at stack traces for the sample `Event` program, the next most advantageous place to parallelize compression is here:\r\n```\r\n#11 0x00007f00743e80fe in R__zipMultipleAlgorithm \r\n#12 0x00007f00729aec25 in TBasket::WriteBuffer \r\n#13 0x00007f00729b53f3 in TBranch::WriteBasket \r\n#14 0x00007f00729b5c95 in TBranch::Fill \r\n#15 0x00007f00729cb630 in TBranchElement::Fill\r\n#16 0x00007f00729cb418 in TBranchElement::Fill \r\n#17 0x00007f00729cb418 in TBranchElement::Fill \r\n#18 0x00007f0072a063f3 in TTree::Fill\r\n```\r\n\r\nThe idea would be to make `WriteBuffer` kick off a separate task, but block `TBranch::Fill` (and a handful of other functions, such as anything that can change the branch's `TFile`) from being called until the `WriteBuffer` task was completed.  Harder than this approach, but not impossible.\r\n"},"comment":{"url":"https://api.github.com/repos/root-mirror/root/issues/comments/252074875","html_url":"https://github.com/root-mirror/root/pull/277#issuecomment-252074875","issue_url":"https://api.github.com/repos/root-mirror/root/issues/277","id":252074875,"user":{"login":"bbockelm","id":1093447,"avatar_url":"https://avatars.githubusercontent.com/u/1093447?v=3","gravatar_id":"","url":"https://api.github.com/users/bbockelm","html_url":"https://github.com/bbockelm","followers_url":"https://api.github.com/users/bbockelm/followers","following_url":"https://api.github.com/users/bbockelm/following{/other_user}","gists_url":"https://api.github.com/users/bbockelm/gists{/gist_id}","starred_url":"https://api.github.com/users/bbockelm/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/bbockelm/subscriptions","organizations_url":"https://api.github.com/users/bbockelm/orgs","repos_url":"https://api.github.com/users/bbockelm/repos","events_url":"https://api.github.com/users/bbockelm/events{/privacy}","received_events_url":"https://api.github.com/users/bbockelm/received_events","type":"User","site_admin":false},"created_at":"2016-10-06T20:11:51Z","updated_at":"2016-10-06T20:11:51Z","body":"I believe there is explicitly no guarantee that `std::atomic<T>` and `T` have the same memory layout - in fact, it's legal for the compiler to implement this with a mutex.  In all likelihood, it is the same layout on X86 but maybe not on obscure-platform-XYZ.\r\n\r\nHowever, since we only need this to be thread-safe for the scope of the `FlushBaskets` call, we can do the thread safety work in transient members and add the intermediate results back to the non-thread-safe persisted members.\r\n\r\nI think."}}
{"actor":{"display_login":"bbockelm"}}