深入理解完美哈希

发表于 2年以前  | 总阅读数:401 次

本文对完美 Hash 的概念进行了梳理,通过 Hash 构建步骤来了解它是如何解决 Hash 冲突的,并比较了 Hash 表和完美 Hash 表。下面介绍常见的 Hash 与 Perfect Hash 函数及它们在不同场景的应用。

散列函数(英语:Hash function)又称散列算法、哈希函数,是一种从任何一种数据中创建小的数字“指纹”的方法。散列函数把消息或数据压缩成摘要,使得数据量变小,将数据的格式固定下来。该函数将数据打乱混合,重新创建一个叫做散列值(hash values,hash codes,hash sums,或 hashes)的指纹。散列值通常用一个短的随机字母和数字组成的字符串来代表。

Hash 函数是一种将集合 S 转换成具有固定长度的、不可逆的的集合 U 的单射,它的值一般为数字合字母的组合,Hash 函数拥有无限的输入空间,却只有有限的输出空间,这意味着 Hash 函数一定会产生碰撞,一个好的 Hash 函数可以显著的降低碰撞概率。Hash 函数一般有一下特征:

  1. 一致性。Hash 函数可以接受任意大小的数据,并输出固定长度的散列值,同时输出不同值的概率应该尽可能一致。如 CityHash128,不管原始数据有多大,计算得到的 hash 值总是 128 bit。
  2. 雪崩效应。原始数据哪怕只有一个字节的修改,得到的 hash 值都会发生巨大的变化。
  3. 单向。只能从原始数据计算得到 hash 值,不能从 hash 值计算得到原始数据。所以散列算法不是加密解密算法,加密解密是可逆的,散列算法是不可逆的。
  4. 避免冲突。几乎不可能找到一个数据和当前计算的这个数据计算出一样的 hash 值,因此散列函数能够确保数据的唯一性。在 Hash 函数保证不同值出现的概率一致的情况下,CityHash128 出现碰撞的概率只有 2 ^ -128。因为不同 Key 的碰撞概率很小,所以在某些情况下我们可以直接使用较短的 Hash 值代替较长原始数据存储。

Hash 函数

常见的 Hash 函数有:

  • CRC32:CRC32 能够快速的生成 32 位 Hash 值,一般在数据库系统或数据传输中出现,用于快速校验数据是否完整;
  • [SipHash] :SipHash 并不是为了速度设计的,与其他 Hash 函数相比速度上不占优势,而提供了 [HashDoS] 保护,是 Rust 中的 Hash 函数的默认实现,最新 Redis 中也在使用 SipHash;
  • MurMurHash:经典快速的 Hash 函数,目前最新的版本是 MurMurHash3,可以生成 32 位或者 128 位 Hash 值;
  • [CityHash] :来自于 Google 实现,受到 MurmurHash 启发,但是比 MurmurHash 更快,可以输出 64 位、128 位或者 256 位 Hash 值。ClickHouse 内置;
  • [xxHash] :针对小数据集速度非常快,支持输出 32 位、64 位、128 位 Hash 值,Github 开源,SSE 支持。ClickHouse 内置。

xxHash 的 benchmark,统计了常用 Hash 函数的性能:

常见用法:

Hash 表:通过 Hash 算法将 Key 均匀映射到不同的位置上,访问单个 key 时可以达到 O(1) 的平均时间复杂度,加快访问速度。

安全 Hash 函数

安全 Hash 函数(或者叫加密 Hash 函数)是一种优秀的 Hash 函数,无法(或者很难)通过 Hash 值猜测出 Key,更精确的说,安全 Hash 必须满足抗碰撞和不可逆两个条件:无法通过 Hash 值的统计学方法逆向,以及无法通过算法层逆向。常见的安全 Hash 算法包括:

  • SHA2,SHA3 系列
  • BLAKE 系列

SHA0、SHA1、MD5 算法已经被认为是不安全的,存在已知的漏洞,不要使用这些不安全的 Hash 函数来签名。

常见用法:

安全 Hash 函数广泛应用于数字签名技术中:对原文进行 Hash 后,将 Hash 结果通过私钥签名,避免原文被泄露或者被修改;工作量证明:如加密货币中挖矿就是通过给定值,计算符合条件的 Hash 输入;文件 ID:在网站下载地址旁往往提供了文件的 MD5 或者 SHA-1,确保下载的文件完整且没有被调包。

HashDoS 与全域 Hash(universal hash)

全域 Hash 解决的是确定性 Hash 算法无法应对特殊输入的问题。在链式 HashMap 里,假设 m = bucket size,考虑我们有输入集合 S 和 Hash 函数 H,其中 H = H’ % m,攻击者在知道 Hash 函数的情况下,容易构造集合 S 使得集合中每一个元素的 Hash 值相同,那 HashMap 会退化成链表。最坏情况下,HashMap 查找的时间复杂度变成了 O(n),插入 n 个元素时需要 O(n2) 的时间复杂度,所以也叫 HashDoS 攻击

全域 Hash 解决的问题是:对于精心构造的输入,冲突率仍然在 1 / m。一个简单的想法是随机选一个 Hash 函数,不是在每一次操作时选一个,而是在输入前选一个 Hash 函数,之后所有的操作都基于该 Hash 函数。

当然 H 也不是随便定义的,具体来说是在 |H| 个 Hash 函数 H 中随机的选择一个 Hash 函数作为所有 key 的 Hash 函数,H 中所有的 Hash 函数 H’ 对于不相等的关键词 x 和 y,使得 H’(x) 和 H’(y) 值相等的函数 H’ 的数量个数等于 |H| / m,[此时冲突概率为 1/m。]

完美 Hash 函数

传统的 Hashmap 总会有分支预测开销与内存对比,最差时间复杂度是 O(n),有那么一种 Hash 函数:完美 Hash 函数( Perfect Hash Function,PHF),它可以在最坏情况下取得 O(1) 的时间复杂度。当然鱼和熊掌不可兼得,完美 Hash 要求有一个静态的输入集合,查找的 Key 必须存在于静态输入集合中,导致使用场景受限。它有几个特点:

  1. 完美 Hash 大部分都要求输入 Key 的集合是已知的,用于提前构建数据结构;
  2. 构造算法复杂,大部分情况下需要比较大的内存,特别是时间复杂度高,需要很长的时间建立索引,构建海量 key 的完美 Hash 可能会失败
  3. 完美 Hash 在实现上并不是只有一个 Hash 函数,而是多个普通 Hash 函数与数据结构算法上的组合,这意味着需要额外空间存储 Hash 冲突信息。

尽管它有一些缺点,但是在一些场景如汉字拼音映射,词典,以及程序中预定义的映射关系都有它的应用。

Perfect Hash Function 对于给定的集合 S,可以将 S 中所有的 Key 映射到整数 [0, m) 中,其中 m >= |S|。当 m = |S| 时,称为最小完美 Hash 函数(Minimal Perfect Hash Function, MPHF)。即作为一个特例,如果完美 Hash 可以将 N 个 key 映射到 0 到 N-1 的整数,那它可以被称为最小完美 Hash 函数。

更进一步,如果 Hash 后给出 key 的顺序没有发生变化,称为完美 Hash 函数是保序的。如果一个 Hash 函数在给定区域不超过 t 次冲突,那这个 Hash 函数称为 t-完美 Hash 函数。

目前开源的 Perfect Hash 库有:

  • [cmph] :C/C++,集合了大部分知名完美 Hash 算法的库,针对不同的数据集合有推荐不同的算法,参数可调,文档不多,LGPL 协议
  • [gperf] :C/C++,专门针对于小数据集完美 Hash 的生成库,GPL 协议;
  • [rust-phf] :使用 CHD 算法生成完美 Hash,使用简单,10 w 个 key 只需 0.4s 就能生成。

下文会讨论 FCH,CHD,PTHASH 是如何巧妙解决了 Hash 冲突并实现了最差 O(1) 时间复杂度的。

完美 Hash 首先需要离线构造得到 Hash 冲突的信息离线保存下来,需要查询时,利用先前生成的信息计算得到唯一的整数 Hash value。

在描述算法之前,先假设:

对于已知大小 n = |S| 的输入集合 S,已知的负载因子 alpha 和参数 c,table 的数量 table_size = n * alpha,桶的数量 m = cn / (log2 n + 1)。一般来说,c 在 2-8 左右,确保每个桶有合适数量的 key,同时不会空出太多的桶。最终所有的 key 会映射到 [0, table_size) 中的 整数。当 alpha = 1table_size = n,为 MPHF

FCH

[A Faster Algorithm for Constructing Minimal Perfect Hash Functions] 由 Fox, Chen, Heath 发明的一种生成完美 Hash 的算法,FCH 是一个相当经典的 Perfect Hash 的实现,后续多种算法均受到 FCH 算法的启发。

FCH 是一种基于二级 Hash 表的完美 Hash 函数:

将数据通过一级 Hash 映射到 T 空间中,然后冲突的数据随机选取新的哈希函数映射到 S 空间中,且 S 空间的大小 m 是冲突数据的平方(例如 T2 中有三个数字产生冲突,则映射到 m 为 9 的 S2 空间中,m 即为避免桶内 Hash 冲突的参数),此时可以容易找到避免碰撞的哈希函数(这个避免冲突的过程称为 position 或者 displace)。最差情况下所需存储空间为 O(n2),但只要适当选择哈希函数减少一级哈希时的碰撞,则可以使预期存储空间为 O(n)

构造 FCH 需要分为三个步骤:

1 . Mapping

Mapping 阶段为了将 60% 的 key 分布到 30 % 的桶里,将 n 个 key 分为 S1 和 S2 两个集合,其中 S1 称为 dense set,key 的数量大概保持在 0.6 * n,S2 为 sparse set,key 的数量大概在 0.4 * n 左右。同时,把所有桶分为两个部分 B1 和 B2,B1 数量 p2 = 0.3 * m,称为 dense buckets,B2 数量 0.7 * m,称为 sparse bucket。使用普通的 Hash 函数如 Cityhash/MurmurHash,将 S1 通过 H1 映射到 B1 中,同样道理将 S2 通过 H2 映射到 B2 中。

用数学语言描述:

2 . Ordering

Ordering 阶段将所有的桶按照桶内冲突的数量排序,冲突数量最多的桶放在最前面。

3 . Searching

Searching 阶段会依次处理每个桶里的冲突,尝试将不重复的 Hash 值分配给每一个 key。经过了上一个阶段排序,该阶段会优先处理冲突最多的桶。对于每一个桶,尝试参数 di, bi,给桶内每一个 key 分配 Hash 值 position(x, di, bi) = (h(x, s2 + b1) + di) mod table_size,这个值在 [0, table_size) 之间,其中 s2 是全局随机种子,bi 是单个 bit,di 是一个从 0 开始的递增的整数,如果 Hash 值在桶内和之前计算过的 Hash 值冲突,则改变 bi 或者 di 直到 Hash 值不发生冲突(为了加速 di 的寻找,原始论文中提出了辅助数据结构和压缩方法,感兴趣可以参考论文)。

处理完冲突后,最终可以得到 m 个参数 bi,di 存入 P 数组中,只占用大概 m * ((log2 n) + 1) = cn bit (这只是理论上的结果,如何存储 bi 和 di 不在我们讨论范围内),即每一个 key 只占用了 c 个 bit。

查询时:对于给定的 key,计算一级 Hash,得到桶编号,通过该桶的 bi,di 和全局 s2 参数来计算二级哈希,即完成了一次查找,可以发现,任何 key 的查询步骤都时相同的,没有循环,即所有步骤都是确定的 O(1)。注意到这里无法判断 key 是否存在。

在 FCH 中,c 越大,构造越快,但是空间利用率越低,特别是 FCH 寻找 MPHF 需要耗费巨量的时间:c = 3 时,1 亿 uint64 的数据需要花费 1 小时以上生成,所以它并不是一个实用的算法。

CHD

为了解决 FCH 构建过慢的问题,出现了基于 FCH 思想的 CHD,一种实现简单的 Perfect Hash 算法,支持 MPHF,空间利用率更高,但 lookup 更慢。

主要不同地方:使用通用 Hash 函数计算出为每一个 key 计算出三个 Hash 值:h, h0, h1,h 用来表示桶号,h0、h1 用来计算最终的 position,position 定义为 position = (h0 + (h1 * d1) + d0) mod table_size

与 FCH 相同,CHD 一共分为三个阶段:

1 . Mapping

Mapping 阶段不需要像 FCH 拆分两个集合,而是直接映射到一个集合中。

使用 c++ 来描述:

for (auto key : keys) {
  auto [h, h0, h1] = hash(key);
  buckets[h].hash = h;
  buckets[h].keys.push_back(make_tuple(h0, h1));
}

2 . Ordering

与 FCH 相同。

sort(buckets.begin(), buckets.end(), [](auto &lhs, auto &rhs){
  return lhs.keys.size() > rhs.keys.size();
});

3 . Searching (也叫 displace)

Searching 阶段同样是处理每个桶里的冲突,不同的是 position 函数发生了变化:为每一个桶初始化一个 pilot,其中 pilot = d0 * table_size + d1,使用 position 公式计算 key 的 Hash 值,发生冲突时,pilot 加上一(相当与 d1 加上 1,此时 position 的结果会发生较大的变化)重新计算 position 直到桶里所有 key 都不发生冲突。

bool_vector position_used, position_used_in_bucket;
vector<uint32> p; // 结果数组

position_used.resize(table_size);
position_used_in_bucket.resize(buckets[0].keys.size());
p.resize(m);

for (auto &bucket : buckets) {
  if (bucket.keys.size() == 0) continue;
  // 单个桶 pilot = d0 * table_size + d1
  int d0 = 0;
  int d1 = 0;
  while(true) {
    bool ok = true;
    position_used_in_bucket.clear();

    for (auto [h0, h1] : bucket.keys) {
      uint64 position = (h0 + (h1 * d1) + d0) % table_size;
      if (position_used[position]) {
        // hash 结果冲突,换一个 pilot
        ok = false;
        break;
      }
      if (position_used_in_bucket[position]) {
        // 桶内 hash 结果冲突,换一个 pilot
        ok = false;
        break;
      }
      position_used_in_bucket[position] = true;
    }

    if (ok) {
      // 单个桶处理完毕
      position_used.union(position_used_in_bucket);
      // pilot 存到 p 数组中
      p[bucket.h] = d0 * table_size + d1;
      break;
    }
    d1++;
    if (d1 >= table_size) {
      d1 = 0;
      d0++;
      if (d0 > table_size) {
        // 构建失败,找不到一个可用的 pilot
        throw ...
      }
    }
  }
}

最终得到的 m 个 pilot 存入 P 数组中。

查询时:对于给定的 key,使用固定出的 Hash 函数计算出 h, h0, h1,根据 P[h] 得到 pilot 与 d0, d1,使用 poisition 易求得 Hash 值,即完成了一次查找(至少 4 次除法 or 求余操作,h < m)

auto [h, h0, h1] = hash(key);
auto pilot = p[h];
auto d0 = pilot / table_size;
auto d1 = pilot % table_size;
return (h0 + (h1 * d1) + d0) % table_size;

结果集 P 中,pilot 往往很小,有压缩空间,在作者的论文中,为了压缩 P 数组的大小,采用 [FN Encoding] 压缩,实现起来更简单。

compact 压缩:给定一系列整数 S,已知 S 中最大的整数 x 需要使用 y 个 bit 表示,我们可以将所有的整数都通过固定 y bit 来表示而不牺牲精度和访问时间。

CHD 算法比较简单,Github 上也有不同语言的实现,[ rust 语言的实现] 。

PTHash

虽然 CHD 实现简单,但其中包含了大量除法求余计算,Encoding 后效率并不高,lookup 耗时过久。最近有一篇文章提出了 [PTHash] 方法,在 FCH 上改进了构建时间,并提高了空间利用率,作者还提供了源代码供参考。

设计思路和 FCH 相似,只不过 position 定义变成了 position(x, pilot) = (h(x, s) xor h(pilot, s)) mod table_size,其中 h 是普通 Hash 函数,x 是 key,s 是全局种子。与 FCH 相比可以提前计算所有 key 的 Hash h(x, s),节约构造时间 。使用 compact 压缩方式效果很好,lookup 耗时也能达到 FCH 水平。

1 . Mapping

与 FCH 相同

2 . Ordering

与 FCH 相同

3 . Searching

使用新的公式计算 position,得到 n 个 pilot,由 position 公式定义,可以发现大部分 pilot 都是比较小的值,作者还介绍了一种 Front-Back Encoding,将结果集前 30% 拆分成 front 集,后 (1- 30%) 拆分为 back 集,代价是运行时多一次分支判断。

由于 front 集合里的桶是最先处理冲突的,冲突发生次数低,大部分 pilot 都比 back 集合内的要小,压缩率更高。将 Front 和 Back 集合里的 pilot 通过 Compact 编码后,称为 Compact-Compact Encoding。

查询时,按照 bucket id 确定去 front 还是 back 集合查询 pilot,不考虑解压过程,只需要两次除法 or 求余操作。

当然这里也可以牺牲部分空间,不做 Front-Back Encoding 以取得更快的查询速度,根据不同的 Encoding 方式,可以在时间&空间上取得平衡:

benchmark

HashMap

HashMap 本质上是根据给定的 key 获得 value 的地址。设计核心主要在于:

  1. HashMap 的空间开销:key 和 value 如何组织?单个 key 需要多少额外空间存储元信息?
  2. HashMap 的查询与插入:如何通过 key 计算出 value 的地址?冲突如何处理?
  3. 不同的 HashMap 不同点在于冲突如何处理,除了常规可读可写的 HashMap,存在只读 HashMap,存储更小,性能更优。

常规 HashMap

在各个语言都有内置的 HashMap 实现,除了使用不同的 Hash 函数,不同实现对 Hash 冲突的解决方案也不同:

  • 拉链法:每一个桶都存着链表的 head 节点,冲突 key 将会被插入链表;
  • 升级红黑树:Java8 在链表长度超过 8 时转换成红黑树;
  • 线性探测法:发现冲突时向后找到第一个没有占用的桶存储,缓存命中率高,负载因子越高,插入效率越低;
  • 多级 Hash 法:单次 Hash 结果冲突时,换一个 Hash 函数直到 Hash 值无冲突。

F14 & B16 系列 HashMap

[F14 & B16] 是一种利用 SIMD 技术进行查找的链式 HashMap,它为每一个 Key 计算两个 Hash 值:H1 和 H2,H1 决定 Key 放在哪一个桶里,H2 用来处理桶内冲突,一般要求负载因子比较高,以获得较高的空间利用率。同时对桶内的 H2 通过 SIMD 指令对比,一次对比 14 个 key 或者 16 个 key,相比 PerfectHashMap,它可以支持动态插入,但是查找性能不如 PerfectHashMap。

PerfectHashMap

有没有办法把 Prefect Hash 利用起来做 HashMap?由于 Perfect Hash 已经映射到 [0, table_size) 内的整数,完全不需要考虑 key 的冲突处理,所以想用起来比较简单:

  • 当 hashmap 的 value 定长时,我们可以直接通过 Hash 值(Index)计算出 value 的 offset,无需使用任何额外空间。
  • 当 hashmap 的 value 不定长时,引入一层 relocation,存储每一个 Hash 值对应 value 的 offset,由于 Hash 值是从 0 递增的,因此 offset 也是递增的,可以通过一定方法去压缩 value offset。

完美 Hash 要求查询的 key 需要存在于输入集内,其他 HashMap 没有这么苛刻的要求,如果使用一个不在输入集中的 key 会怎么样呢?从 CHD 算法的 lookup 过程来分析,输入未知 key 时可以认为返回一个随机的 Index,如果我们需要确认 key 是否存在 HashMap 里,需要将原始 key 存下来放在 Index 对应的 Value 中,查询到 Index 后再对比一次才能确认 key 是否存在。

PerfectHashMap 一般用法是先离线生成 map 信息,再读到 buffer 里,或者像 rust-phf 一样编译时内置到二进制,直接读 P 数组,如果 HashMap 特别大,还可以通过 mmap 只读方式载入到内存中。

Benchmark

测试设备:MacBookPro m1 Pro 32G,MacOS 12.4,clang 13.1.6。

比较对象:

  • unordered_map:标准库自带的 HashMap,链式实现;
  • Folly F14:Facebook HashMap 实现,使用 SIMD 优化查询过程;
  • abseil swiss table:Google HashMap 实现,为速度优化,包括使用额外指针的 node_hash_map,与原地存储适合小 value 的 flat_hash_map;
  • PTHashMap:PTHash + Value offset 映射,(内部使用 CityHash128),c = 7, alpha = 0.98,Compact-Compact Encoding,Value offset 使用 MILC 压缩。不存储 key;
  • PTHashMap3:与 PTHashMap 参数不同:c = 3, alpha=0.99;
  • PTHashMap10:与 PTHashMap 参数不同:c = 10, alpha=0.94。
string

测试场景:输入 100w 随机不重复不定长字符串(平均长度 8 bytes)作为 key,value 与 key 相同。全部随机 lookup 一遍。

meta data 排除了 key 和 Value 之后统计占用内存大小,folly 使用 computeStats() 统计内存数据;total memory 值插入所有 key 后使用 gpertools 统计占用内存大小,包含 key 和 value 部分;注意 PTHashMap meta data 统计单位是 bit。

uint64

测试场景:输入 100w 随机不重复 uint64 数字作为 key,value 与 key 相同,全部随机 lookup 一遍。

由于该场景数据是长度固定,PTHashMap 去掉了 Value offset 映射表。

结论

完美 Hash 的概念扩展了 Hash 的使用场景,最近出现的新型完美 Hash 算法在运行速度&构建速度上取得了较大的进步,针对海量只读场景使用完美 HashMap 不仅可以提升速度,同时能够节省大量内存占用。

本文由哈喽比特于2年以前收录,如有侵权请联系我们。
文章来源:https://mp.weixin.qq.com/s/M8Wcj8sZ7UF1CMr887Puog

 相关推荐

刘强东夫妇:“移民美国”传言被驳斥

京东创始人刘强东和其妻子章泽天最近成为了互联网舆论关注的焦点。有关他们“移民美国”和在美国购买豪宅的传言在互联网上广泛传播。然而,京东官方通过微博发言人发布的消息澄清了这些传言,称这些言论纯属虚假信息和蓄意捏造。

发布于:1年以前  |  808次阅读  |  详细内容 »

博主曝三大运营商,将集体采购百万台华为Mate60系列

日前,据博主“@超能数码君老周”爆料,国内三大运营商中国移动、中国电信和中国联通预计将集体采购百万台规模的华为Mate60系列手机。

发布于:1年以前  |  770次阅读  |  详细内容 »

ASML CEO警告:出口管制不是可行做法,不要“逼迫中国大陆创新”

据报道,荷兰半导体设备公司ASML正看到美国对华遏制政策的负面影响。阿斯麦(ASML)CEO彼得·温宁克在一档电视节目中分享了他对中国大陆问题以及该公司面临的出口管制和保护主义的看法。彼得曾在多个场合表达了他对出口管制以及中荷经济关系的担忧。

发布于:1年以前  |  756次阅读  |  详细内容 »

抖音中长视频App青桃更名抖音精选,字节再发力对抗B站

今年早些时候,抖音悄然上线了一款名为“青桃”的 App,Slogan 为“看见你的热爱”,根据应用介绍可知,“青桃”是一个属于年轻人的兴趣知识视频平台,由抖音官方出品的中长视频关联版本,整体风格有些类似B站。

发布于:1年以前  |  648次阅读  |  详细内容 »

威马CDO:中国每百户家庭仅17户有车

日前,威马汽车首席数据官梅松林转发了一份“世界各国地区拥车率排行榜”,同时,他发文表示:中国汽车普及率低于非洲国家尼日利亚,每百户家庭仅17户有车。意大利世界排名第一,每十户中九户有车。

发布于:1年以前  |  589次阅读  |  详细内容 »

研究发现维生素 C 等抗氧化剂会刺激癌症生长和转移

近日,一项新的研究发现,维生素 C 和 E 等抗氧化剂会激活一种机制,刺激癌症肿瘤中新血管的生长,帮助它们生长和扩散。

发布于:1年以前  |  449次阅读  |  详细内容 »

苹果据称正引入3D打印技术,用以生产智能手表的钢质底盘

据媒体援引消息人士报道,苹果公司正在测试使用3D打印技术来生产其智能手表的钢质底盘。消息传出后,3D系统一度大涨超10%,不过截至周三收盘,该股涨幅回落至2%以内。

发布于:1年以前  |  446次阅读  |  详细内容 »

千万级抖音网红秀才账号被封禁

9月2日,坐拥千万粉丝的网红主播“秀才”账号被封禁,在社交媒体平台上引发热议。平台相关负责人表示,“秀才”账号违反平台相关规定,已封禁。据知情人士透露,秀才近期被举报存在违法行为,这可能是他被封禁的部分原因。据悉,“秀才”年龄39岁,是安徽省亳州市蒙城县人,抖音网红,粉丝数量超1200万。他曾被称为“中老年...

发布于:1年以前  |  445次阅读  |  详细内容 »

亚马逊股东起诉公司和贝索斯,称其在购买卫星发射服务时忽视了 SpaceX

9月3日消息,亚马逊的一些股东,包括持有该公司股票的一家养老基金,日前对亚马逊、其创始人贝索斯和其董事会提起诉讼,指控他们在为 Project Kuiper 卫星星座项目购买发射服务时“违反了信义义务”。

发布于:1年以前  |  444次阅读  |  详细内容 »

苹果上线AppsbyApple网站,以推广自家应用程序

据消息,为推广自家应用,苹果现推出了一个名为“Apps by Apple”的网站,展示了苹果为旗下产品(如 iPhone、iPad、Apple Watch、Mac 和 Apple TV)开发的各种应用程序。

发布于:1年以前  |  442次阅读  |  详细内容 »

特斯拉美国降价引发投资者不满:“这是短期麻醉剂”

特斯拉本周在美国大幅下调Model S和X售价,引发了该公司一些最坚定支持者的不满。知名特斯拉多头、未来基金(Future Fund)管理合伙人加里·布莱克发帖称,降价是一种“短期麻醉剂”,会让潜在客户等待进一步降价。

发布于:1年以前  |  441次阅读  |  详细内容 »

光刻机巨头阿斯麦:拿到许可,继续对华出口

据外媒9月2日报道,荷兰半导体设备制造商阿斯麦称,尽管荷兰政府颁布的半导体设备出口管制新规9月正式生效,但该公司已获得在2023年底以前向中国运送受限制芯片制造机器的许可。

发布于:1年以前  |  437次阅读  |  详细内容 »

马斯克与库克首次隔空合作:为苹果提供卫星服务

近日,根据美国证券交易委员会的文件显示,苹果卫星服务提供商 Globalstar 近期向马斯克旗下的 SpaceX 支付 6400 万美元(约 4.65 亿元人民币)。用于在 2023-2025 年期间,发射卫星,进一步扩展苹果 iPhone 系列的 SOS 卫星服务。

发布于:1年以前  |  430次阅读  |  详细内容 »

𝕏(推特)调整隐私政策,可拿用户发布的信息训练 AI 模型

据报道,马斯克旗下社交平台𝕏(推特)日前调整了隐私政策,允许 𝕏 使用用户发布的信息来训练其人工智能(AI)模型。新的隐私政策将于 9 月 29 日生效。新政策规定,𝕏可能会使用所收集到的平台信息和公开可用的信息,来帮助训练 𝕏 的机器学习或人工智能模型。

发布于:1年以前  |  428次阅读  |  详细内容 »

荣耀CEO谈华为手机回归:替老同事们高兴,对行业也是好事

9月2日,荣耀CEO赵明在采访中谈及华为手机回归时表示,替老同事们高兴,觉得手机行业,由于华为的回归,让竞争充满了更多的可能性和更多的魅力,对行业来说也是件好事。

发布于:1年以前  |  423次阅读  |  详细内容 »

AI操控无人机能力超越人类冠军

《自然》30日发表的一篇论文报道了一个名为Swift的人工智能(AI)系统,该系统驾驶无人机的能力可在真实世界中一对一冠军赛里战胜人类对手。

发布于:1年以前  |  423次阅读  |  详细内容 »

AI生成的蘑菇科普书存在可致命错误

近日,非营利组织纽约真菌学会(NYMS)发出警告,表示亚马逊为代表的电商平台上,充斥着各种AI生成的蘑菇觅食科普书籍,其中存在诸多错误。

发布于:1年以前  |  420次阅读  |  详细内容 »

社交媒体平台𝕏计划收集用户生物识别数据与工作教育经历

社交媒体平台𝕏(原推特)新隐私政策提到:“在您同意的情况下,我们可能出于安全、安保和身份识别目的收集和使用您的生物识别信息。”

发布于:1年以前  |  411次阅读  |  详细内容 »

国产扫地机器人热销欧洲,国产割草机器人抢占欧洲草坪

2023年德国柏林消费电子展上,各大企业都带来了最新的理念和产品,而高端化、本土化的中国产品正在不断吸引欧洲等国际市场的目光。

发布于:1年以前  |  406次阅读  |  详细内容 »

罗永浩吐槽iPhone15和14不会有区别,除了序列号变了

罗永浩日前在直播中吐槽苹果即将推出的 iPhone 新品,具体内容为:“以我对我‘子公司’的了解,我认为 iPhone 15 跟 iPhone 14 不会有什么区别的,除了序(列)号变了,这个‘不要脸’的东西,这个‘臭厨子’。

发布于:1年以前  |  398次阅读  |  详细内容 »
 相关文章
Android插件化方案 5年以前  |  237269次阅读
vscode超好用的代码书签插件Bookmarks 2年以前  |  8108次阅读
 目录