Remove temporary allocations - #39

Merged
jgwalkup merged 4 commits into
mainfrom
iss22-remove-f64
Nov 12, 2025
Merged

Remove temporary allocations#39
jgwalkup merged 4 commits into
mainfrom
iss22-remove-f64

Conversation

@Mikolaj-A-Kowalski

@Mikolaj-A-KowalskiMikolaj-A-Kowalski commented Jun 24, 2025

Copy link
Copy Markdown
Contributor

Builds on #34, related to #22

There was an implicit conversion to float64 taking place due to a cast to the Python's list (and hence Python's float). This resulted in a serious (factor ~10) degradation in performance, which should now be fixed.

The problem was ultimately related to how pandas handles partial assignments in DataFrames and Series. If the data is assigned to from a higher precision expression, the dtype of the Series may be implicitly changed, which causes a temporary memory allocation. For example:

importpandasaspdimportnumpyasnpdf=pd.DataFrame({"f32": np.ones(2, dtype="float32")})
# Here `dtype` of df will change to float64 # Temporary memory allocation is taking placedf.iloc[1:2] =np.float64(1/3)

Please note that the behaviour is a bit peculiar and perhaps unintuitive. Pandas will not change dtype if it is "not necessary", that is the new value can be represented exactly in the prior dtype. e.g. :

importpandasaspdimportnumpyasnpdf=pd.DataFrame({"f32": np.ones(2, dtype="float32")})
# Here `dtype` of df will remain float32 since 2.0 can be represented exactlydf.iloc[1:2] =np.float64(2.0)

The implicit conversion to float64 was causing some DataFrames to change their dtype to "float64", which in turn caused Max_Uptake (in grid.uptake method) getting repeatability changed from "float32" to "float64", which appears to have been the main performance bottleneck.

Tagging @bioatmosphere explicitly since you were interested during the meeting yesterday ;-)

sjavisand others added 4 commits June 6, 2025 18:07
There was an implicit conversion to float64 taking place due to a cast
to the Python's list (and hence Python's float). This resulted in a
serious (factor ~10) degradation in performance, which should now be
fixed.
The performance degradation was a result of temporary allocation
performed by pandas when a dtype of a frame was implicitly changed
in updates of the form e.g.:
```python
import pandas as pd
import numpy as np
df = pd.DataFrame({"f32": np.ones(2, dtype="float32")})
df.iloc[1:2] = np.float64(1/3)
```
since pandas 2.1, such operations raise a FutureWarning. All occurences
of that warning in DEMENTpy are resolved in this commit.
Comment threadsrc/grid.py
choose_taxa = np.zeros((self.n_taxa,self.gridsize), dtype='int8')
for i in range(self.n_taxa):
choose_taxa[i,:] = np.random.choice([1,0], self.gridsize, replace=True, p=[frequencies[i], 1-frequencies[i]])
choose_taxa[i,:] = np.random.binomial(1, frequencies[i], self.gridsize)

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When I changed the numbers back to "float32" this sampling started failing saying that the probabilities do not sum to 1.0. I presume they must be converted to "float64" before getting summed inside np.random.random_choice.

I have changed the sampling to binominal, which i believe should be equivalent and would avoid the summation errors.

Comment threadsrc/grid.py
[Enzyme_Loss,
Enzyme_Loss.mul(self.Enz_Attrib['N_cost'].tolist()*self.gridsize,axis=0),
Enzyme_Loss.mul(self.Enz_Attrib['P_cost'].tolist()*self.gridsize,axis=0)],
Enzyme_Loss.mul(np.repeat(self.Enz_Attrib['N_cost'].values, self.gridsize), axis=0),

@Mikolaj-A-KowalskiMikolaj-A-KowalskiJun 24, 2025

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The 'float64' was appearing here.

tolist method would return a list of Python's floats, which are double precision.

@jgwalkup
jgwalkup marked this pull request as ready for review September 2, 2025 14:49
@jgwalkup
jgwalkup self-requested a review September 30, 2025 18:30
@jgwalkup
jgwalkup merged commit a5f8711 into mainNov 12, 2025
@jgwalkup
jgwalkup deleted the iss22-remove-f64 branch November 12, 2025 14:08
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@Mikolaj-A-Kowalski@jgwalkup@sjavis
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Remove temporary allocations - #39

Merged
jgwalkup merged 4 commits into
mainfrom
iss22-remove-f64
Nov 12, 2025
Merged

Remove temporary allocations#39
jgwalkup merged 4 commits into
mainfrom
iss22-remove-f64

Conversation

@Mikolaj-A-Kowalski

@Mikolaj-A-KowalskiMikolaj-A-Kowalski commented Jun 24, 2025

Copy link
Copy Markdown
Contributor

Builds on #34, related to #22

There was an implicit conversion to float64 taking place due to a cast to the Python's list (and hence Python's float). This resulted in a serious (factor ~10) degradation in performance, which should now be fixed.

The problem was ultimately related to how pandas handles partial assignments in DataFrames and Series. If the data is assigned to from a higher precision expression, the dtype of the Series may be implicitly changed, which causes a temporary memory allocation. For example:

importpandasaspdimportnumpyasnpdf=pd.DataFrame({"f32": np.ones(2, dtype="float32")})
# Here `dtype` of df will change to float64 # Temporary memory allocation is taking placedf.iloc[1:2] =np.float64(1/3)

Please note that the behaviour is a bit peculiar and perhaps unintuitive. Pandas will not change dtype if it is "not necessary", that is the new value can be represented exactly in the prior dtype. e.g. :

importpandasaspdimportnumpyasnpdf=pd.DataFrame({"f32": np.ones(2, dtype="float32")})
# Here `dtype` of df will remain float32 since 2.0 can be represented exactlydf.iloc[1:2] =np.float64(2.0)

The implicit conversion to float64 was causing some DataFrames to change their dtype to "float64", which in turn caused Max_Uptake (in grid.uptake method) getting repeatability changed from "float32" to "float64", which appears to have been the main performance bottleneck.

Tagging @bioatmosphere explicitly since you were interested during the meeting yesterday ;-)

sjavisand others added 4 commits June 6, 2025 18:07
There was an implicit conversion to float64 taking place due to a cast
to the Python's list (and hence Python's float). This resulted in a
serious (factor ~10) degradation in performance, which should now be
fixed.
The performance degradation was a result of temporary allocation
performed by pandas when a dtype of a frame was implicitly changed
in updates of the form e.g.:
```python
import pandas as pd
import numpy as np
df = pd.DataFrame({"f32": np.ones(2, dtype="float32")})
df.iloc[1:2] = np.float64(1/3)
```
since pandas 2.1, such operations raise a FutureWarning. All occurences
of that warning in DEMENTpy are resolved in this commit.
Comment threadsrc/grid.py
choose_taxa = np.zeros((self.n_taxa,self.gridsize), dtype='int8')
for i in range(self.n_taxa):
choose_taxa[i,:] = np.random.choice([1,0], self.gridsize, replace=True, p=[frequencies[i], 1-frequencies[i]])
choose_taxa[i,:] = np.random.binomial(1, frequencies[i], self.gridsize)

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When I changed the numbers back to "float32" this sampling started failing saying that the probabilities do not sum to 1.0. I presume they must be converted to "float64" before getting summed inside np.random.random_choice.

I have changed the sampling to binominal, which i believe should be equivalent and would avoid the summation errors.

Comment threadsrc/grid.py
[Enzyme_Loss,
Enzyme_Loss.mul(self.Enz_Attrib['N_cost'].tolist()*self.gridsize,axis=0),
Enzyme_Loss.mul(self.Enz_Attrib['P_cost'].tolist()*self.gridsize,axis=0)],
Enzyme_Loss.mul(np.repeat(self.Enz_Attrib['N_cost'].values, self.gridsize), axis=0),

@Mikolaj-A-KowalskiMikolaj-A-KowalskiJun 24, 2025

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The 'float64' was appearing here.

tolist method would return a list of Python's floats, which are double precision.

@jgwalkup
jgwalkup marked this pull request as ready for review September 2, 2025 14:49
@jgwalkup
jgwalkup self-requested a review September 30, 2025 18:30
@jgwalkup
jgwalkup merged commit a5f8711 into mainNov 12, 2025
@jgwalkup
jgwalkup deleted the iss22-remove-f64 branch November 12, 2025 14:08
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@Mikolaj-A-Kowalski@jgwalkup@sjavis
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Remove temporary allocations - #39

Merged
jgwalkup merged 4 commits into
mainfrom
iss22-remove-f64
Nov 12, 2025
Merged

Remove temporary allocations#39
jgwalkup merged 4 commits into
mainfrom
iss22-remove-f64

Conversation

@Mikolaj-A-Kowalski

@Mikolaj-A-KowalskiMikolaj-A-Kowalski commented Jun 24, 2025

Copy link
Copy Markdown
Contributor

Builds on #34, related to #22

There was an implicit conversion to float64 taking place due to a cast to the Python's list (and hence Python's float). This resulted in a serious (factor ~10) degradation in performance, which should now be fixed.

The problem was ultimately related to how pandas handles partial assignments in DataFrames and Series. If the data is assigned to from a higher precision expression, the dtype of the Series may be implicitly changed, which causes a temporary memory allocation. For example:

importpandasaspdimportnumpyasnpdf=pd.DataFrame({"f32": np.ones(2, dtype="float32")})
# Here `dtype` of df will change to float64 # Temporary memory allocation is taking placedf.iloc[1:2] =np.float64(1/3)

Please note that the behaviour is a bit peculiar and perhaps unintuitive. Pandas will not change dtype if it is "not necessary", that is the new value can be represented exactly in the prior dtype. e.g. :

importpandasaspdimportnumpyasnpdf=pd.DataFrame({"f32": np.ones(2, dtype="float32")})
# Here `dtype` of df will remain float32 since 2.0 can be represented exactlydf.iloc[1:2] =np.float64(2.0)

The implicit conversion to float64 was causing some DataFrames to change their dtype to "float64", which in turn caused Max_Uptake (in grid.uptake method) getting repeatability changed from "float32" to "float64", which appears to have been the main performance bottleneck.

Tagging @bioatmosphere explicitly since you were interested during the meeting yesterday ;-)

sjavisand others added 4 commits June 6, 2025 18:07
There was an implicit conversion to float64 taking place due to a cast
to the Python's list (and hence Python's float). This resulted in a
serious (factor ~10) degradation in performance, which should now be
fixed.
The performance degradation was a result of temporary allocation
performed by pandas when a dtype of a frame was implicitly changed
in updates of the form e.g.:
```python
import pandas as pd
import numpy as np
df = pd.DataFrame({"f32": np.ones(2, dtype="float32")})
df.iloc[1:2] = np.float64(1/3)
```
since pandas 2.1, such operations raise a FutureWarning. All occurences
of that warning in DEMENTpy are resolved in this commit.
Comment threadsrc/grid.py
choose_taxa = np.zeros((self.n_taxa,self.gridsize), dtype='int8')
for i in range(self.n_taxa):
choose_taxa[i,:] = np.random.choice([1,0], self.gridsize, replace=True, p=[frequencies[i], 1-frequencies[i]])
choose_taxa[i,:] = np.random.binomial(1, frequencies[i], self.gridsize)

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When I changed the numbers back to "float32" this sampling started failing saying that the probabilities do not sum to 1.0. I presume they must be converted to "float64" before getting summed inside np.random.random_choice.

I have changed the sampling to binominal, which i believe should be equivalent and would avoid the summation errors.

Comment threadsrc/grid.py
[Enzyme_Loss,
Enzyme_Loss.mul(self.Enz_Attrib['N_cost'].tolist()*self.gridsize,axis=0),
Enzyme_Loss.mul(self.Enz_Attrib['P_cost'].tolist()*self.gridsize,axis=0)],
Enzyme_Loss.mul(np.repeat(self.Enz_Attrib['N_cost'].values, self.gridsize), axis=0),

@Mikolaj-A-KowalskiMikolaj-A-KowalskiJun 24, 2025

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The 'float64' was appearing here.

tolist method would return a list of Python's floats, which are double precision.

@jgwalkup
jgwalkup marked this pull request as ready for review September 2, 2025 14:49
@jgwalkup
jgwalkup self-requested a review September 30, 2025 18:30
@jgwalkup
jgwalkup merged commit a5f8711 into mainNov 12, 2025
@jgwalkup
jgwalkup deleted the iss22-remove-f64 branch November 12, 2025 14:08
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@Mikolaj-A-Kowalski@jgwalkup@sjavis
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Remove temporary allocations - #39

Merged
jgwalkup merged 4 commits into
mainfrom
iss22-remove-f64
Nov 12, 2025
Merged

Remove temporary allocations#39
jgwalkup merged 4 commits into
mainfrom
iss22-remove-f64

Conversation

@Mikolaj-A-Kowalski

@Mikolaj-A-KowalskiMikolaj-A-Kowalski commented Jun 24, 2025

Copy link
Copy Markdown
Contributor

Builds on #34, related to #22

There was an implicit conversion to float64 taking place due to a cast to the Python's list (and hence Python's float). This resulted in a serious (factor ~10) degradation in performance, which should now be fixed.

The problem was ultimately related to how pandas handles partial assignments in DataFrames and Series. If the data is assigned to from a higher precision expression, the dtype of the Series may be implicitly changed, which causes a temporary memory allocation. For example:

importpandasaspdimportnumpyasnpdf=pd.DataFrame({"f32": np.ones(2, dtype="float32")})
# Here `dtype` of df will change to float64 # Temporary memory allocation is taking placedf.iloc[1:2] =np.float64(1/3)

Please note that the behaviour is a bit peculiar and perhaps unintuitive. Pandas will not change dtype if it is "not necessary", that is the new value can be represented exactly in the prior dtype. e.g. :

importpandasaspdimportnumpyasnpdf=pd.DataFrame({"f32": np.ones(2, dtype="float32")})
# Here `dtype` of df will remain float32 since 2.0 can be represented exactlydf.iloc[1:2] =np.float64(2.0)

The implicit conversion to float64 was causing some DataFrames to change their dtype to "float64", which in turn caused Max_Uptake (in grid.uptake method) getting repeatability changed from "float32" to "float64", which appears to have been the main performance bottleneck.

Tagging @bioatmosphere explicitly since you were interested during the meeting yesterday ;-)

sjavisand others added 4 commits June 6, 2025 18:07
There was an implicit conversion to float64 taking place due to a cast
to the Python's list (and hence Python's float). This resulted in a
serious (factor ~10) degradation in performance, which should now be
fixed.
The performance degradation was a result of temporary allocation
performed by pandas when a dtype of a frame was implicitly changed
in updates of the form e.g.:
```python
import pandas as pd
import numpy as np
df = pd.DataFrame({"f32": np.ones(2, dtype="float32")})
df.iloc[1:2] = np.float64(1/3)
```
since pandas 2.1, such operations raise a FutureWarning. All occurences
of that warning in DEMENTpy are resolved in this commit.
Comment threadsrc/grid.py
choose_taxa = np.zeros((self.n_taxa,self.gridsize), dtype='int8')
for i in range(self.n_taxa):
choose_taxa[i,:] = np.random.choice([1,0], self.gridsize, replace=True, p=[frequencies[i], 1-frequencies[i]])
choose_taxa[i,:] = np.random.binomial(1, frequencies[i], self.gridsize)

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When I changed the numbers back to "float32" this sampling started failing saying that the probabilities do not sum to 1.0. I presume they must be converted to "float64" before getting summed inside np.random.random_choice.

I have changed the sampling to binominal, which i believe should be equivalent and would avoid the summation errors.

Comment threadsrc/grid.py
[Enzyme_Loss,
Enzyme_Loss.mul(self.Enz_Attrib['N_cost'].tolist()*self.gridsize,axis=0),
Enzyme_Loss.mul(self.Enz_Attrib['P_cost'].tolist()*self.gridsize,axis=0)],
Enzyme_Loss.mul(np.repeat(self.Enz_Attrib['N_cost'].values, self.gridsize), axis=0),

@Mikolaj-A-KowalskiMikolaj-A-KowalskiJun 24, 2025

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The 'float64' was appearing here.

tolist method would return a list of Python's floats, which are double precision.

@jgwalkup
jgwalkup marked this pull request as ready for review September 2, 2025 14:49
@jgwalkup
jgwalkup self-requested a review September 30, 2025 18:30
@jgwalkup
jgwalkup merged commit a5f8711 into mainNov 12, 2025
@jgwalkup
jgwalkup deleted the iss22-remove-f64 branch November 12, 2025 14:08
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@Mikolaj-A-Kowalski@jgwalkup@sjavis
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Remove temporary allocations - #39

Merged
jgwalkup merged 4 commits into
mainfrom
iss22-remove-f64
Nov 12, 2025
Merged

Remove temporary allocations#39
jgwalkup merged 4 commits into
mainfrom
iss22-remove-f64

Conversation

@Mikolaj-A-Kowalski

@Mikolaj-A-KowalskiMikolaj-A-Kowalski commented Jun 24, 2025

Copy link
Copy Markdown
Contributor

Builds on #34, related to #22

There was an implicit conversion to float64 taking place due to a cast to the Python's list (and hence Python's float). This resulted in a serious (factor ~10) degradation in performance, which should now be fixed.

The problem was ultimately related to how pandas handles partial assignments in DataFrames and Series. If the data is assigned to from a higher precision expression, the dtype of the Series may be implicitly changed, which causes a temporary memory allocation. For example:

importpandasaspdimportnumpyasnpdf=pd.DataFrame({"f32": np.ones(2, dtype="float32")})
# Here `dtype` of df will change to float64 # Temporary memory allocation is taking placedf.iloc[1:2] =np.float64(1/3)

Please note that the behaviour is a bit peculiar and perhaps unintuitive. Pandas will not change dtype if it is "not necessary", that is the new value can be represented exactly in the prior dtype. e.g. :

importpandasaspdimportnumpyasnpdf=pd.DataFrame({"f32": np.ones(2, dtype="float32")})
# Here `dtype` of df will remain float32 since 2.0 can be represented exactlydf.iloc[1:2] =np.float64(2.0)

The implicit conversion to float64 was causing some DataFrames to change their dtype to "float64", which in turn caused Max_Uptake (in grid.uptake method) getting repeatability changed from "float32" to "float64", which appears to have been the main performance bottleneck.

Tagging @bioatmosphere explicitly since you were interested during the meeting yesterday ;-)

sjavisand others added 4 commits June 6, 2025 18:07
There was an implicit conversion to float64 taking place due to a cast
to the Python's list (and hence Python's float). This resulted in a
serious (factor ~10) degradation in performance, which should now be
fixed.
The performance degradation was a result of temporary allocation
performed by pandas when a dtype of a frame was implicitly changed
in updates of the form e.g.:
```python
import pandas as pd
import numpy as np
df = pd.DataFrame({"f32": np.ones(2, dtype="float32")})
df.iloc[1:2] = np.float64(1/3)
```
since pandas 2.1, such operations raise a FutureWarning. All occurences
of that warning in DEMENTpy are resolved in this commit.
Comment threadsrc/grid.py
choose_taxa = np.zeros((self.n_taxa,self.gridsize), dtype='int8')
for i in range(self.n_taxa):
choose_taxa[i,:] = np.random.choice([1,0], self.gridsize, replace=True, p=[frequencies[i], 1-frequencies[i]])
choose_taxa[i,:] = np.random.binomial(1, frequencies[i], self.gridsize)

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When I changed the numbers back to "float32" this sampling started failing saying that the probabilities do not sum to 1.0. I presume they must be converted to "float64" before getting summed inside np.random.random_choice.

I have changed the sampling to binominal, which i believe should be equivalent and would avoid the summation errors.

Comment threadsrc/grid.py
[Enzyme_Loss,
Enzyme_Loss.mul(self.Enz_Attrib['N_cost'].tolist()*self.gridsize,axis=0),
Enzyme_Loss.mul(self.Enz_Attrib['P_cost'].tolist()*self.gridsize,axis=0)],
Enzyme_Loss.mul(np.repeat(self.Enz_Attrib['N_cost'].values, self.gridsize), axis=0),

@Mikolaj-A-KowalskiMikolaj-A-KowalskiJun 24, 2025

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The 'float64' was appearing here.

tolist method would return a list of Python's floats, which are double precision.

@jgwalkup
jgwalkup marked this pull request as ready for review September 2, 2025 14:49
@jgwalkup
jgwalkup self-requested a review September 30, 2025 18:30
@jgwalkup
jgwalkup merged commit a5f8711 into mainNov 12, 2025
@jgwalkup
jgwalkup deleted the iss22-remove-f64 branch November 12, 2025 14:08
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@Mikolaj-A-Kowalski@jgwalkup@sjavis
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Remove temporary allocations - #39

Merged
jgwalkup merged 4 commits into
mainfrom
iss22-remove-f64
Nov 12, 2025
Merged

Remove temporary allocations#39
jgwalkup merged 4 commits into
mainfrom
iss22-remove-f64

Conversation

@Mikolaj-A-Kowalski

@Mikolaj-A-KowalskiMikolaj-A-Kowalski commented Jun 24, 2025

Copy link
Copy Markdown
Contributor

Builds on #34, related to #22

There was an implicit conversion to float64 taking place due to a cast to the Python's list (and hence Python's float). This resulted in a serious (factor ~10) degradation in performance, which should now be fixed.

The problem was ultimately related to how pandas handles partial assignments in DataFrames and Series. If the data is assigned to from a higher precision expression, the dtype of the Series may be implicitly changed, which causes a temporary memory allocation. For example:

importpandasaspdimportnumpyasnpdf=pd.DataFrame({"f32": np.ones(2, dtype="float32")})
# Here `dtype` of df will change to float64 # Temporary memory allocation is taking placedf.iloc[1:2] =np.float64(1/3)

Please note that the behaviour is a bit peculiar and perhaps unintuitive. Pandas will not change dtype if it is "not necessary", that is the new value can be represented exactly in the prior dtype. e.g. :

importpandasaspdimportnumpyasnpdf=pd.DataFrame({"f32": np.ones(2, dtype="float32")})
# Here `dtype` of df will remain float32 since 2.0 can be represented exactlydf.iloc[1:2] =np.float64(2.0)

The implicit conversion to float64 was causing some DataFrames to change their dtype to "float64", which in turn caused Max_Uptake (in grid.uptake method) getting repeatability changed from "float32" to "float64", which appears to have been the main performance bottleneck.

Tagging @bioatmosphere explicitly since you were interested during the meeting yesterday ;-)

sjavisand others added 4 commits June 6, 2025 18:07
There was an implicit conversion to float64 taking place due to a cast
to the Python's list (and hence Python's float). This resulted in a
serious (factor ~10) degradation in performance, which should now be
fixed.
The performance degradation was a result of temporary allocation
performed by pandas when a dtype of a frame was implicitly changed
in updates of the form e.g.:
```python
import pandas as pd
import numpy as np
df = pd.DataFrame({"f32": np.ones(2, dtype="float32")})
df.iloc[1:2] = np.float64(1/3)
```
since pandas 2.1, such operations raise a FutureWarning. All occurences
of that warning in DEMENTpy are resolved in this commit.
Comment threadsrc/grid.py
choose_taxa = np.zeros((self.n_taxa,self.gridsize), dtype='int8')
for i in range(self.n_taxa):
choose_taxa[i,:] = np.random.choice([1,0], self.gridsize, replace=True, p=[frequencies[i], 1-frequencies[i]])
choose_taxa[i,:] = np.random.binomial(1, frequencies[i], self.gridsize)

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When I changed the numbers back to "float32" this sampling started failing saying that the probabilities do not sum to 1.0. I presume they must be converted to "float64" before getting summed inside np.random.random_choice.

I have changed the sampling to binominal, which i believe should be equivalent and would avoid the summation errors.

Comment threadsrc/grid.py
[Enzyme_Loss,
Enzyme_Loss.mul(self.Enz_Attrib['N_cost'].tolist()*self.gridsize,axis=0),
Enzyme_Loss.mul(self.Enz_Attrib['P_cost'].tolist()*self.gridsize,axis=0)],
Enzyme_Loss.mul(np.repeat(self.Enz_Attrib['N_cost'].values, self.gridsize), axis=0),

@Mikolaj-A-KowalskiMikolaj-A-KowalskiJun 24, 2025

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The 'float64' was appearing here.

tolist method would return a list of Python's floats, which are double precision.

@jgwalkup
jgwalkup marked this pull request as ready for review September 2, 2025 14:49
@jgwalkup
jgwalkup self-requested a review September 30, 2025 18:30
@jgwalkup
jgwalkup merged commit a5f8711 into mainNov 12, 2025
@jgwalkup
jgwalkup deleted the iss22-remove-f64 branch November 12, 2025 14:08
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@Mikolaj-A-Kowalski@jgwalkup@sjavis
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Remove temporary allocations - #39

Merged
jgwalkup merged 4 commits into
mainfrom
iss22-remove-f64
Nov 12, 2025
Merged

Remove temporary allocations#39
jgwalkup merged 4 commits into
mainfrom
iss22-remove-f64

Conversation

@Mikolaj-A-Kowalski

@Mikolaj-A-KowalskiMikolaj-A-Kowalski commented Jun 24, 2025

Copy link
Copy Markdown
Contributor

Builds on #34, related to #22

There was an implicit conversion to float64 taking place due to a cast to the Python's list (and hence Python's float). This resulted in a serious (factor ~10) degradation in performance, which should now be fixed.

The problem was ultimately related to how pandas handles partial assignments in DataFrames and Series. If the data is assigned to from a higher precision expression, the dtype of the Series may be implicitly changed, which causes a temporary memory allocation. For example:

importpandasaspdimportnumpyasnpdf=pd.DataFrame({"f32": np.ones(2, dtype="float32")})
# Here `dtype` of df will change to float64 # Temporary memory allocation is taking placedf.iloc[1:2] =np.float64(1/3)

Please note that the behaviour is a bit peculiar and perhaps unintuitive. Pandas will not change dtype if it is "not necessary", that is the new value can be represented exactly in the prior dtype. e.g. :

importpandasaspdimportnumpyasnpdf=pd.DataFrame({"f32": np.ones(2, dtype="float32")})
# Here `dtype` of df will remain float32 since 2.0 can be represented exactlydf.iloc[1:2] =np.float64(2.0)

The implicit conversion to float64 was causing some DataFrames to change their dtype to "float64", which in turn caused Max_Uptake (in grid.uptake method) getting repeatability changed from "float32" to "float64", which appears to have been the main performance bottleneck.

Tagging @bioatmosphere explicitly since you were interested during the meeting yesterday ;-)

sjavisand others added 4 commits June 6, 2025 18:07
There was an implicit conversion to float64 taking place due to a cast
to the Python's list (and hence Python's float). This resulted in a
serious (factor ~10) degradation in performance, which should now be
fixed.
The performance degradation was a result of temporary allocation
performed by pandas when a dtype of a frame was implicitly changed
in updates of the form e.g.:
```python
import pandas as pd
import numpy as np
df = pd.DataFrame({"f32": np.ones(2, dtype="float32")})
df.iloc[1:2] = np.float64(1/3)
```
since pandas 2.1, such operations raise a FutureWarning. All occurences
of that warning in DEMENTpy are resolved in this commit.
Comment threadsrc/grid.py
choose_taxa = np.zeros((self.n_taxa,self.gridsize), dtype='int8')
for i in range(self.n_taxa):
choose_taxa[i,:] = np.random.choice([1,0], self.gridsize, replace=True, p=[frequencies[i], 1-frequencies[i]])
choose_taxa[i,:] = np.random.binomial(1, frequencies[i], self.gridsize)

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When I changed the numbers back to "float32" this sampling started failing saying that the probabilities do not sum to 1.0. I presume they must be converted to "float64" before getting summed inside np.random.random_choice.

I have changed the sampling to binominal, which i believe should be equivalent and would avoid the summation errors.

Comment threadsrc/grid.py
[Enzyme_Loss,
Enzyme_Loss.mul(self.Enz_Attrib['N_cost'].tolist()*self.gridsize,axis=0),
Enzyme_Loss.mul(self.Enz_Attrib['P_cost'].tolist()*self.gridsize,axis=0)],
Enzyme_Loss.mul(np.repeat(self.Enz_Attrib['N_cost'].values, self.gridsize), axis=0),

@Mikolaj-A-KowalskiMikolaj-A-KowalskiJun 24, 2025

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The 'float64' was appearing here.

tolist method would return a list of Python's floats, which are double precision.

@jgwalkup
jgwalkup marked this pull request as ready for review September 2, 2025 14:49
@jgwalkup
jgwalkup self-requested a review September 30, 2025 18:30
@jgwalkup
jgwalkup merged commit a5f8711 into mainNov 12, 2025
@jgwalkup
jgwalkup deleted the iss22-remove-f64 branch November 12, 2025 14:08
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@Mikolaj-A-Kowalski@jgwalkup@sjavis
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Remove temporary allocations - #39

Merged
jgwalkup merged 4 commits into
mainfrom
iss22-remove-f64
Nov 12, 2025
Merged

Remove temporary allocations#39
jgwalkup merged 4 commits into
mainfrom
iss22-remove-f64

Conversation

@Mikolaj-A-Kowalski

@Mikolaj-A-KowalskiMikolaj-A-Kowalski commented Jun 24, 2025

Copy link
Copy Markdown
Contributor

Builds on #34, related to #22

There was an implicit conversion to float64 taking place due to a cast to the Python's list (and hence Python's float). This resulted in a serious (factor ~10) degradation in performance, which should now be fixed.

The problem was ultimately related to how pandas handles partial assignments in DataFrames and Series. If the data is assigned to from a higher precision expression, the dtype of the Series may be implicitly changed, which causes a temporary memory allocation. For example:

importpandasaspdimportnumpyasnpdf=pd.DataFrame({"f32": np.ones(2, dtype="float32")})
# Here `dtype` of df will change to float64 # Temporary memory allocation is taking placedf.iloc[1:2] =np.float64(1/3)

Please note that the behaviour is a bit peculiar and perhaps unintuitive. Pandas will not change dtype if it is "not necessary", that is the new value can be represented exactly in the prior dtype. e.g. :

importpandasaspdimportnumpyasnpdf=pd.DataFrame({"f32": np.ones(2, dtype="float32")})
# Here `dtype` of df will remain float32 since 2.0 can be represented exactlydf.iloc[1:2] =np.float64(2.0)

The implicit conversion to float64 was causing some DataFrames to change their dtype to "float64", which in turn caused Max_Uptake (in grid.uptake method) getting repeatability changed from "float32" to "float64", which appears to have been the main performance bottleneck.

Tagging @bioatmosphere explicitly since you were interested during the meeting yesterday ;-)

sjavisand others added 4 commits June 6, 2025 18:07
There was an implicit conversion to float64 taking place due to a cast
to the Python's list (and hence Python's float). This resulted in a
serious (factor ~10) degradation in performance, which should now be
fixed.
The performance degradation was a result of temporary allocation
performed by pandas when a dtype of a frame was implicitly changed
in updates of the form e.g.:
```python
import pandas as pd
import numpy as np
df = pd.DataFrame({"f32": np.ones(2, dtype="float32")})
df.iloc[1:2] = np.float64(1/3)
```
since pandas 2.1, such operations raise a FutureWarning. All occurences
of that warning in DEMENTpy are resolved in this commit.
Comment threadsrc/grid.py
choose_taxa = np.zeros((self.n_taxa,self.gridsize), dtype='int8')
for i in range(self.n_taxa):
choose_taxa[i,:] = np.random.choice([1,0], self.gridsize, replace=True, p=[frequencies[i], 1-frequencies[i]])
choose_taxa[i,:] = np.random.binomial(1, frequencies[i], self.gridsize)

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When I changed the numbers back to "float32" this sampling started failing saying that the probabilities do not sum to 1.0. I presume they must be converted to "float64" before getting summed inside np.random.random_choice.

I have changed the sampling to binominal, which i believe should be equivalent and would avoid the summation errors.

Comment threadsrc/grid.py
[Enzyme_Loss,
Enzyme_Loss.mul(self.Enz_Attrib['N_cost'].tolist()*self.gridsize,axis=0),
Enzyme_Loss.mul(self.Enz_Attrib['P_cost'].tolist()*self.gridsize,axis=0)],
Enzyme_Loss.mul(np.repeat(self.Enz_Attrib['N_cost'].values, self.gridsize), axis=0),

@Mikolaj-A-KowalskiMikolaj-A-KowalskiJun 24, 2025

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The 'float64' was appearing here.

tolist method would return a list of Python's floats, which are double precision.

@jgwalkup
jgwalkup marked this pull request as ready for review September 2, 2025 14:49
@jgwalkup
jgwalkup self-requested a review September 30, 2025 18:30
@jgwalkup
jgwalkup merged commit a5f8711 into mainNov 12, 2025
@jgwalkup
jgwalkup deleted the iss22-remove-f64 branch November 12, 2025 14:08
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@Mikolaj-A-Kowalski@jgwalkup@sjavis