如何在 Erlang 二进制文件中一次高效地设置一位而不需要命令式?

发布于 2024-08-16 06:33:24 字数 442 浏览 4 评论 0原文

作为练习,我正在研究埃拉托斯特尼筛法的并行实现。作为其中的一部分,我正在实现一系列位图,每个数字使用一位来节省内存。一次读取一位似乎工作正常,但设置它们很慢,特别是当我使用大型二进制文件时。

getBit(Bin, N, Size)->
    R=Size-N-1,
    <<_:N,Bit:1,_:R>> = Bin,
    Bit.

setBit(Bin, N, Size)->
    R=Size-N-1,
    <<A:N,_:1,B:R>> = Bin,
    <<A:N,1:1,B:R>>.

有没有办法在函数式 Erlang 中很好地做到这一点,也许类似于数组的工作方式? 我已经阅读过有关 hipe_bifs:bytearray_update 的内容,但更愿意保持我的编码风格正常运行。

As an exercise I am working on a parallel implementation of the Sieve of Eratosthenes. As part of that I am implementing a sequence of bitmaps, using one bit per number to save memory. Reading bits one at a time appear to work fine, but setting them is slow, especially when I use large binaries.

getBit(Bin, N, Size)->
    R=Size-N-1,
    <<_:N,Bit:1,_:R>> = Bin,
    Bit.

setBit(Bin, N, Size)->
    R=Size-N-1,
    <<A:N,_:1,B:R>> = Bin,
    <<A:N,1:1,B:R>>.

Is there a way to do this well in functional Erlang, perhaps similar to how Arrays work?
I have read about hipe_bifs:bytearray_update but would prefer to keep my coding style functional.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

凤舞天涯 2024-08-23 06:33:24

您可以将位图存储为整数(如果它们不长于〜1000位):

-module(z).
-export([get_bit/2, set_bit/2]).

get_bit(N, B) -> N band bit_to_int(B) > 0.
set_bit(N, B) -> N bor bit_to_int(B).

bit_to_int(B) -> 1 bsl B.

您可以尝试您的版本,不传递大小,并填充到字节:

getBit(Bin, N)->
    <<_:N/bitstring,Bit:1,_/bitstring>> = Bin,
    Bit.

setBit(Bin, N)->
    <<A:N,_:1,B/bitstring>> = Bin,
    <<A:N,1:1,B>>.

%OR:
setBit(Bin, N)->
    PSize = 8 - ((N + 1) rem 8),
    <<A:N,_:1, Pad:PSize,B/bytes>> = Bin,
    <<A:N,1:1,Pad:PSize,B>>.

可能更好或更差:-)

You can store your bitmaps as integers (if they are not longer than ~1000 bits):

-module(z).
-export([get_bit/2, set_bit/2]).

get_bit(N, B) -> N band bit_to_int(B) > 0.
set_bit(N, B) -> N bor bit_to_int(B).

bit_to_int(B) -> 1 bsl B.

You might try your version w/o passing the Size, and padding to bytes:

getBit(Bin, N)->
    <<_:N/bitstring,Bit:1,_/bitstring>> = Bin,
    Bit.

setBit(Bin, N)->
    <<A:N,_:1,B/bitstring>> = Bin,
    <<A:N,1:1,B>>.

%OR:
setBit(Bin, N)->
    PSize = 8 - ((N + 1) rem 8),
    <<A:N,_:1, Pad:PSize,B/bytes>> = Bin,
    <<A:N,1:1,Pad:PSize,B>>.

Can be better or worse :-)

不再见 2024-08-23 06:33:24

一般来说,对于 getset 操作来说,复杂度都为 O(log(n)) ,这是再好不过的了,因为 Erlang 是函数式的语言。您可以使用某种类型的树来归档O(log(n))arraydictgb_treesgb_sets 模块执行此操作。

因此,如果您需要使其尽可能快,则必须使用命令式 - 您可以尝试 hipe_bifs 模块、流程字典和 ets 表。

Generally one can not do it better then with complexity of O(log(n)) for both get and set operations, since Erlang is functional language. You can archive O(log(n)) using some type of trees. array, dict, gb_trees and gb_sets modules does this.

So if you need to make it as fast as possible you have to go imperative - you could try hipe_bifs module, process dictionary and ets tables.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文